【发布时间】:2011-06-16 17:34:28
【问题描述】:
我有一个 ExecutorService 管理许多 Callables。 Callables 运行的任务主要是黑盒转换和数字运算。在某些情况下,正在转换的数据会振荡,线程将需要一个多小时才能完成。相比之下,大多数线程在一分钟内完成。
已确定来自长时间运行线程的数据不相关。我想中断运行时间超过一定时间的任何线程。最好的方法是什么?
【问题讨论】:
标签: java multithreading threadpool
我有一个 ExecutorService 管理许多 Callables。 Callables 运行的任务主要是黑盒转换和数字运算。在某些情况下,正在转换的数据会振荡,线程将需要一个多小时才能完成。相比之下,大多数线程在一分钟内完成。
已确定来自长时间运行线程的数据不相关。我想中断运行时间超过一定时间的任何线程。最好的方法是什么?
【问题讨论】:
标签: java multithreading threadpool
当达到超时时,使用 ScheduleExecutorService 将任务安排到taskFuture.cancel(true) 长时间运行的任务。如果任务在此之前完成,则不会被取消。
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){
final Future<T> future = service.submit(c);
canceller.schedule(new Callable<Void>(){
public Void call(){
future.cancel(true);
return null;
}
}, timeoutMS, TimeUnit.MILLI_SECONDS);
return future;
}
【讨论】:
Runnable 而不是Callable - 减少返回类型的混乱,无需返回任何内容。
canceller.schedule(...) 缩短为 canceller.schedule(() -> future.cancel(true), timeoutMS, TimeUnit. MILLI_SECONDS);
您可以像其他答案一样取消未来等,但您需要确保您的“数字运算”线程可以处理中断并优雅地终止。你说这是一个黑盒操作——你有多大把握在黑盒内主动检查线程的中断状态?如果不是,则无法通过中断取消它。黑匣子的书写需要考虑中断。
【讨论】:
您最好的方法是再引入一位 Executor。您可以使用 ScheduledExecutorService 取消所有长时间运行的任务,例如:
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newScheduledThreadPool(1);
public void executeTask(Callable<?> c){
final Future<?> future = service.submit(c);
canceller.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, SECONDS_UNTIL_TIMEOUT, TimeUnit.SECONDS);
}
【讨论】:
您可以获得相应的 Futures 列表(在您提交 Callable 时创建)及其启动时间。
然后,另一个任务可以每分钟检查是否有某个任务运行了超过定义的时间,如果是,则在未来调用 cancel(true)。已完成的期货将从列表中删除。
【讨论】:
你可以用这个方法
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
throws InterruptedException
并将最大超时设置为一分钟。如果您的线程花费的时间超过了它,它就会被中止。
【讨论】: