2017-02-22 9 views
0

私は、チェックポイント付きのマラソンランナーを示すプログラムを作成したいと考えています。 5人のランナーが作成され、最初のチェックポイントに達するまでにランダムな時間がかかります。ランナーは、他のランナーのすべてがチェックポイントに達するまで、チェックポイントで停止する必要があります。 2つのチェックポイントとフィニッシュラインがあります。ここで同じタイプの別のものがタスクを完了するまで、Runnableを一時停止するにはどうすればよいですか?

は、私はこれを実装するための最良の方法だろうと思ったいくつかの基本的なコードです:

public class Main { 
public static void main(String[] args) { 
    int i = 1; 
    Runner[] runners = new Runner[5]; 

    //Create 5 Runners 
    for (Runner runner : runners) { 
     runner = new Runner(i++); 
     runner.run(); 
    } 

    //Wait for runners to arrive at 1st checkpoint 
    for (Runner runner : runners) { 
     runner.arrivedAt1stCheckpoint(); 
    } 

    //Wait for runenrs to arrive at 2nd checkpoint 
    for (Runner runner : runners) { 
     runner.arrivedAt2ndCheckpoint(); 
    } 

    //Wait for runners to finish race 
    for (Runner runner : runners) { 
     runner.finishedRace(); 
    } 
}} 

public class Runner implements Runnable { 

    public final int runnerID; 
    Random randomGenerator = new Random(); 

    public Runner(int i) { 
     this.runnerID = i; 
    } 

    @Override 
    public void run() { 
     System.out.printf("Runner %d exists\n", runnerID); 
    } 

    public boolean arrivedAt1stCheckpoint() { 
     sleepThread(); 
     System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID); 
     return true; 
    } 

    public boolean arrivedAt2ndCheckpoint() { 
     System.out.printf("Runner %d arrived at 2nd checkpoint\n", runnerID); 
     sleepThread(); 
     return true; 
    } 

    public boolean finishedRace() { 
     System.out.printf("Runner %d finished race\n", runnerID); 
     sleepThread(); 
     return true; 
    } 

    private void sleepThread() { 
     try { 
      Thread.sleep(randomGenerator.nextInt(1000)); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Runner.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    }} 

は明らかにこれはほとんどの構造であると私は書くことを求めていないよので、私は原料の束を欠けています私のためのプログラム全体。 ここで私の主な問題は、ランナークラスの各インスタンスが何らかの形で他のインスタンスと通信し、すべてのランナーがチェックポイントに達するまでプログラム全体をスリープ状態にすることです。 「ポインタ」が役に立ちます。ありがとう!

+1

あなたは 'CountDownLatch'を考えましたか? – MadProgrammer

+0

聞いたことがない、私はそれをチェックします – OverflowingJava

+1

あなたはForkJoinPoolを試してみるとよいでしょう。 invokeAllメソッドを見てみましょう。 –

答えて

1

すべてのランナーがチェックポイントに行ったタイミングをチェックする手段が必要です。私たちはランナー(配列、ArrayListを、などのコレクションを維持した場合これは

public class Runner implements Runnable {  
    private boolean atFirstCheckpoint = false; 
    // ... More checkpoint booleans 
    // ... Rest of the class 

    public boolean hasReachedFirstCheckpoint() { 
     return atFirstCheckpoint; 
    } 
} 

など、checkpoint2、あなたのランナーは、それがcheckpoint1になったかどうかを追跡するために、ブール変数の数を持つことによって行うことができます)、ランナーがすべてチェックポイントに達したかどうかをチェックするメソッドを作成できます。

public boolean everyoneHasReachedFirstCheckpoint(Runner[] runners) { 
    for (Runner r : runners) { 
     if (!r.hasReachedFirstCheckpoint()) { 
      return false; 
     } 
     return true; 
    } 
} 

我々は、このチェックを実行するために、私たちarrivedAt1stCheckpoint()を変更することができます。 Runnerオブジェクトは、配列内の他のすべてのランナーがチェックポイントに到達するまでスリープします。

public boolean arrivedAt1stCheckpoint(Runner[] runners) { 
    this.atFirstCheckPoint = true; 
    System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID); 
    while (!everyoneHasReachedFirstCheckpoint(runners)) { 
     sleepThread(); 
    } 

    return true; 
} 

編集:それは、whileループの実行中に全体ランナースレッドがあなたのsleepThread()メソッドに応じて、時間のX量のために停止することを念頭に置いて価値があります。つまり、誰もがチェックポイントを作っているかどうかをチェックする前に、ランナーが文字通りXの時間眠っていることを意味します。

編集:実行者インターフェイスやスレッドプールを使用すると、ランナー(スレッド)を試して管理することができます。

1

CyclicBarrierまたはCountDownLatchを考慮する必要があります。 CyclicBarrierを使用した簡単なスニペットを次に示します。希望希望数、あなたがバリアに待ちたいスレッドに沿っ関門を通過し、障壁に待つ必要があるのスレッドで今、この

int BarrierCount = 4; 
CyclicBarrier barrier = new CyclicBarrier(BarrierCount); 

for (int i = 0; i <= BarrierCount; i++) { 
    (new AppThreadsForBarrier(barrier, "name"+i, ...)).start(); 
} 

のようなもの、として何かに障壁を設定し

以下

class AppThreadsForBarrier extends Thread { 

    // barrier along with other variables you need for your thread 
    public AppThreadsForBarrier(CyclicBarrier barrier, String name, ....) { 
    .. 

    public void run() { 
     try { 
      Thread.sleep(duration); 
      System.out.println(Thread.currentThread().getName() + " is calling await()"); 
      barrier.await(); 
      System.out.println(Thread.currentThread().getName() + " has started running again"); 
      .. 

を行うことができますがありCyclicBarrierを用V/sのたCountDownLatchを使用する場所に関していくつかのニュアンスがありますが、これはあなたに始めるために絵を与える必要があります。

関連する問題