Java:为ThreadPool中的线程设置超时

sk2*_*212 9 java multithreading timeout

我想为线程池中执行的线程设置超时.目前我有以下代码:

ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {            
    Runnable worker = new WorkerThread(l);
    executor.execute(worker);
}       

executor.shutdown();
while (!executor.isTerminated()) {

}
Run Code Online (Sandbox Code Playgroud)

代码只是将一个大的对象列表拆分为子列表,并在单个线程中处理这些子列表.但这不是重点.

我想给线程池中的每个单线程一个超时.对于池中只有一个线程,我找到了以下解决方案:

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!");
}
Run Code Online (Sandbox Code Playgroud)

但这不适用于多个线程.也许我必须将每个线程放在一个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?!
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止效果很好.

那么下一个问题是如何中断一个超时的线程?我尝试fut.cancel(true)在工作线程的一些关键循环中添加以下构造:

if(Thread.interrupted()) {
    System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!");
        return;
}
Run Code Online (Sandbox Code Playgroud)

因此工作线程在超时后被"杀死".这是一个好的解决方案吗?

此外:是否有可能获得通过Future接口超时的线程的名称?目前,我必须在Thread.interrupted()构造的if条件中打印出名称.

感谢帮助!

问候

Fil*_*dor 3

你见过这个吗?ExecutorService.invokeAll

它应该正是您想要的:调用一组工作人员,如果花费太长时间,则让他们超时。

评论后编辑 - (新想法):您可以使用 CountDownLatch等待任务完成并通过 超时await(long timeout, TimeUnit unit)!然后您甚至可以执行 shutdownNow 并查看哪些任务花费了太长时间......

编辑2:

为了更清楚地说明:

  1. 完成后,让每个 Worker 都使用 CountDownLatch 进行倒计时。
  2. 在主执行线程中,await所述锁存器超时。
  3. 当该调用返回时,您可以检查锁存器的计数以查看是否发生超时(如果>0)。
  4. a) count = 0,所有任务均按时完成。b) 如果没有,则循环 Futures 并检查它们的isDone. 您不必对 ExecutorService 调用 shutdown。
  5. 如果不再需要执行器,请调用 shutdown。

注意:工作人员可以在超时和调用 Future 的 isDone() 之间同时完成。