![](/img/trans.png)
[英]Java how to timeout a thread WITHOUT using future.get and without blocking parent thread
[英]How to end a task(timeout a thread) (by rising interrupt) using executor.execute and future.get() without blocking the main thread
我嘗試在執行器服務中使用未來,它可以在不阻塞主線程的情況下工作。 然而,這最終會創建雙倍數量的線程,這是不可取的。 在下面的代碼中,我能夠在沒有阻塞的情況下使用 future.get() 但我必須創建雙倍數量的線程
for (int i : array) {
executor.execute(() -> {
Future f = new FutureTask(() -> {
Goring goring = new Goring();
goring.goring(i);
}, null);
Thread thread = new Thread((Runnable) f);
thread.start();
try {
f.get(1, TimeUnit.NANOSECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException|RuntimeException e) {
// TODO Auto-generated catch block
// System.out.println(e.getMessage());
e.printStackTrace();
f.cancel(true);
}
});
}
executor.shutdown();
}
通常我會推薦使用ExecutorService.invokeAll ,它允許提交任意數量的超時任務,並在超時到期時取消任何尚未完成的任務。
但是您在評論中聲明您希望能夠在較小的並行組中提交任務,例如一次不超過三個並行運行。
您可以創建具有有限並行度的線程池:
ExecutorService executor = Executors.newFixedThreadPool(3);
這里的挑戰是您希望在任務啟動時開始超時,而不是在提交任務時。 由於提交的任務無法訪問自己的 Future,我將使用SynchronousQueue來等待從提交線程傳遞的 Future:
ScheduledExecutorService cancelScheduler =
Executors.newSingleThreadScheduledExecutor();
for (int i : array) {
SynchronousQueue<Runnable> cancelQueue = new SynchronousQueue<>();
Future<?> task = executor.submit(() -> {
Runnable canceler = cancelQueue.take();
cancelScheduler.schedule(canceler, 5, TimeUnit.SECONDS);
Goring goring = new Goring();
goring.goring(i);
return null;
});
cancelQueue.put(() -> task.cancel(true));
}
executor.shutdown();
cancelScheduler.shutdown();
顧名思義, Executors.newSingleThreadScheduledExecutor()只使用一個線程進行所有調度,這非常適合您的目的,因為計划任務只調用 Future.cancel,所花費的時間可以忽略不計。
return null;
在任務中,從 lambda 返回一個值使其成為 Callable 而不是 Runnable。 (Runnable 的run
方法有一個返回類型void
,所以返回值的存在告訴編譯器這個 lambda 不可能代表一個 Runnable。)這意味着它的簽名隱含地throws Exception
,所以沒有必要捕獲 InterruptedException可能由cancelQueue.take()
拋出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.