スレッド プール内で実行されるスレッドのタイムアウトを設定したいと考えています。現時点では、次のコードがあります。
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
このコードは、オブジェクトの大きなリストをサブリストに分割し、これらのサブリストをシングル スレッド内で処理するだけです。しかし、これはポイントではありません。
スレッドプール内の各スレッドにタイムアウトを与えたい。プール内のスレッドが 1 つだけの場合、次の解決策が見つかりました。
Future<?> future = null;
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
future = executor.submit(worker);
}
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
}
しかし、これは複数のスレッドでは機能しません。たぶん、各スレッドをリストに入れ、List<Future>
このリストを繰り返し処理し、各future
オブジェクトのタイムアウトを設定する必要がありますか?
助言がありますか?
CountDownLatch を使用した後に編集:
CountDownLatch doneSignal = new CountDownLatch(partition.size());
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newFixedThreadPool(8);
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
tasks.add(executor.submit(doneSignal, worker));
}
doneSignal.await(1, TimeUnit.SECONDS);
if (doneSignal.getCount() > 0) {
for (Future<?> fut : tasks) {
if (!fut.isDone()) {
System.out.println("Task " + fut + " has not finshed!");
//fut.cancel(true) Maybe we can interrupt a thread this way?!
}
}
}
これまでのところうまくいきます。
次の質問は、タイムアウトになったスレッドを中断する方法です。fut.cancel(true)
ワーカースレッドのいくつかの重要なループに次の構成を追加しようとしました:
if(Thread.interrupted()) {
System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!");
return;
}
そのため、ワーカー スレッドはタイムアウト後に「強制終了」されます。これは良い解決策ですか?
さらに: タイムアウトしたスレッドの名前をFuture
インターフェイス経由で取得することは可能ですか? 現時点では、Thread.interrupted()
コンストラクトの if 条件で名前を出力する必要があります。
手伝ってくれてありがとう!
よろしく