2

3つのスレッドをデプロイするaction()というメソッドがあります。デプロイされた各スレッドまたはワーカースレッドは、ブール型の単一インスタンス変数がtrueであることに基づいてwhileループに分類されます。たとえば、boolean doWork = trueの場合、各スレッドにはwhile(doWork){}ループがあります。

スレッドが終了すると、ジョブはdoWorkをfalseに設定し、すべてのスレッドのループを停止します。次に、どういうわけかメインスレッドにaction()メソッドをリコールさせて、別のジョブを実行するためにスレッドを再デプロイできるようにしたいと思います。(ワーカースレッドの1つを使用してaction()メソッドを呼び出しても大丈夫ですか?)action()メソッドを呼び出して、どういうわけか死ぬと、ワーカースレッドは終了しますか?

簡単にするために、例を2つのスレッドに制限しました

ありがとう

class TestThreads{
    boolean doWork = true;

    void action(){
         ThreadOne t1 = new ThreadOne();
         ThreadTwo t2 = new ThreadTwo();
    }

    //innerclasses

    class ThreadOne implements Runnable{
          Thread trd1;
          public ThreadOne(){//constructor
              if(trd1 == null){
                   trd1 = new Thread(this);
                   trd1.start();
              }
          }
          @Override
          public void run(){
              while(doWork){
                   //random condition
                   //would set doWork = false;
                   //stop all other threads
              }
              action();//is the method in the main class
          }
    }
    class ThreadTwo implements Runnable{
          Thread trd2;
          public ThreadTwo(){//constroctor
              if(trd2 == null){
                   trd2 = new Thread(this);
                   trd2.start();
              }
          }
          @Override
          public void run(){
              while(doWork){
                   //random condition
                   //would set doWork = false;
                   //stop all other threads
              }
              action();//is the method in the main class
          }
    }

}
4

5 に答える 5

4

この実装はどうですか?

doWorkクラスメンバー、現在アクティブなスレッドのカウンター、および同期オブジェクトを宣言します。

private volatile boolean doWork = true;
private AtomicInteger activeThreads;
private Object locker = new Object();

主に:

while(true) {
    // call action to start N threads
    activeThreads = new AtomicInteger(N);
    action(N);
    // barrier to wait for threads to finish
    synchronized(locker) {
       while(activeThreads.get() > 0) {
           locker.wait();
       }
    }
}

スレッド本体:

public void run() {
   while(doWork) {
      ...
      // if task finished set doWork to false
   }

   // signal main thread that I've finished
   synchronized(locker) {
      activeThreads.getAndDecrement();
      locker.notify();
   }
}
于 2012-02-01T17:57:36.930 に答える
3

スケルトンコード

// OP said 3 threads...
ExecutorService xs = Executors.newFixedThreadPool(3);

...

// repeat the following as many times as you want...
// this is the setup for his 3 threads - as Callables.

ArrayList<Callable<T>> my3Callables = new ArrayList<Callable<T>>();
my3Callables.add(callable1);
my3Callables.add(callable2);
my3Callables.add(callable3);

try {
   List<Future<T>> futures = xs.invokeAll(my3Callables );

   // below code may not be needed but is useful for catching any exceptions
   for (Future<T> future : futures) {
      T t = future.get();
      // do something with T if wanted
   }
}
catch (ExecutionException ee) {
  // do something
}
catch (CancellationException ce) {
  // do something
}
catch (InterruptedException ie) {
  // do something
}
于 2012-02-01T17:56:25.993 に答える
2

コメントを拡張します(@babernathyがこれを彼の回答に追加したとしても)。

通常、ある作業を実行したいスレッドのプールがあり、実行したい作業の項目を管理するメインスレッドがある場合、ExecutorServiceは理想的なフレームワークを提供します。

メインオブジェクトで、(必要な数のスレッドを使用して)サービスのインスタンスを作成し、作業を生成するときにそれをサービスに送信すると、サービスは次の利用可能なスレッドを選択します。プールして実行します。

特定の作業が完了したかどうかを知ることに依存している場合は、スレッドのようなものを使用してCountDownLatch、スレッドが作業を完了した時期を追跡できます。私のポイントでは、この種の活動にはかなりの数の既存のフレームワークがあり、苦痛を何度も繰り返す必要はありません...

于 2012-02-01T17:59:04.180 に答える
1

コードなしで正確な解決策を提供するのは少し難しいです。一連のワーカースレッドにいくつかのタスクを与え、それらが完了すると、さらに多くのタスクを与えるという生産者/消費者パターンを説明しているように思えます。

これは、何をすべきかを説明するOKの仕事をするWebページです。

また、Runnablesを送信して実行させることができるExecutorServiceも確認してください。

于 2012-02-01T17:43:45.193 に答える
1

簡単な解決策は、メインスレッドをスリープ状態にすることです。

static boolean doWork = true; // better to use AtomicBoolean

void action() {

    // start workers, which eventually set doWork = false

    while (doWork) {    
        Thread.sleep(/**time in millis**/); // main thread waits for workers
    }

    // logic to run action() again, etc.

}

メインスレッドはワーカーを開始し、定期的にウェイクアップして、ワーカーが終了したかどうかを確認します。メインスレッドは「アービター」であるため、その子の1つによって復活するためだけに死ぬべきではないでしょう。

参照

于 2012-02-01T17:49:22.537 に答える