6

私はシミュレーションシステムに取り組んでおり、各タイムステップで多くのモデルをシミュレートする必要があります。FixedThreadPoolを使用して、計算を高速化しました。

ExecutorService executor = Executors.newFixedThreadPool(nThread);
for (Model m : models) {
  executor.execute( m.simulationTask() );
}
executor.shutdown();
while ( ! executor.awaitTermination(10, TimeUnit.MINUTES) ) { 
  System.out.println("wait"); 
}

execute()現在、を呼び出した後、エグゼキュータを新しいタスクに使用することはできませんshutdown()。エグゼキュータをリセットして、次のシミュレーションステップで既存のエグゼキュータ(およびそのスレッド)を再利用できるようにする方法はありますか?

4

4 に答える 4

7

コードをいくらか再構築すれば、エグゼキュータサービスを再利用できます。

Collection<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>(16);
for (Model m : models) {
  tasks.add(m.simulationTask());
}

ExecutorService executor = Executors.newFixedThreadPool(nThread);
try {
  executor.invokeAll(tasks);
} catch(InterruptedException ie) {
  // Handle this
}

基本的に、すべてのタスクを収集して実行し、実行を待ってから続行します。もちろん、代わりに、タイムステップごとに新しいエグゼキュータサービスを使用することもできますが、少なくともオプションがあります。

警告:コードをコンパイルしなかったため、エラーが発生する可能性があります。また、便宜上、整数パラメーター型を想定しました。

于 2012-01-27T16:03:25.177 に答える
1

インターフェイスの独自の実装を作成できExecutorます。それを超えて、私が知っているデフォルトの実装のほとんどは、スレッドを刈り取り、後でメモリのクリーンアップを行うshutdown()ので、(私の知る限り)事前に作成されたソリューションはありません。

これにより多くのクリーンアップとガベージコレクションが行われる可能性があることを考えるとshutdown()、新しいものを取得するよりも再起動する方がよい理由は明確ではありません。おそらく、機能を追加するのではなく、メソッドの一時停止/再開セットを使用して拡張する方法についてExecutorのチュートリアルを調べる必要があります。シャットダウンを解除します。ThreadPoolExecutor

于 2012-01-27T15:57:39.870 に答える
1

ExecutorServiceをクラスのメンバーとして宣言し、必要に応じて再利用します。それ以上のタスクを受け入れないため、shutDown()を呼び出さないでください。もちろん、タスクは適切に終了する必要があり、ある時点で終了する必要もあります。

于 2012-01-27T16:07:43.507 に答える
0

別のものを取得するだけExecutorServiceです。とにかくオーバーヘッドは最小限です。

同じエグゼキュータを再利用することを主張する場合は、独自のバリアメカニズムを実装できます。新しいタスクを送信すると、カウンターをアトミックにインクリメントします。タスクが終了したら、カウンターをアトミックにデクリメントします。メインスレッドでは、カウンターがゼロになるまで待ちます。何かのようなもの:

// globally visible objects
AtomicInteger counter = new AtomicInteger(0);
Object signal = new Object();

ExecutorService executor = Executors.newFixedThreadPool(nThread);
for (Model m : models) {
  counter.getAndIncrement();
  executor.execute( m.simulationTask() );
}

synchronized(signal) {
   while(count.get() > 0) {
       signal.wait();
   }
}

run次に、タスクの内部:

public void run() {
    // original code
    // at the end:
    synchronized(signal) {
       counter.getAndDecrement();
       signal.notify();
    }        
}
于 2012-01-27T15:58:56.377 に答える