我想爲在線程池中執行的線程設置超時。目前,我有下面的代碼:Java:爲ThreadPool中的線程設置超時
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
代碼只是拆分對象的大名單變成子列表並處理根單絲中的這些子表。但這不是重點。
我想給線程池中的每個單線程超時。對於只有一個池線程我發現了以下解決方案:
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>
列表中,並遍歷這個列表併爲每個對象設置一個超時時間?
有什麼建議嗎?
編輯使用CountDownLatch AFTER:
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條件中打印出名稱。
感謝您的幫助!
Regards
是的,它適用於更多,只是將期貨保持在列表中。 – Fildor
請不要用這種方式來思考線程。有些事情正在完成,如果需要超過一定的時間,則需要超時。這不是什麼線索可能發生在做這項工作,它是*工作*。也許兩個線程正在進行合作。當時可能沒有線程正在處理那項工作。但它是你想要停止或超時的*工作*,而不是可能或可能不會發生的線程或線程。這種細微的觀點轉變對正確思考線程非常重要,這樣您就可以收到良好的設計。 –
@DavidSchwartz好點,但是可能有些作品是完全獨立於彼此的情況。我不知道OP是否確實是這樣,但在這裏看起來就是這樣。 – fge