我有一个ExecutorService管理一些Callables。 Callables运行的任务主要是黑盒转换和数字运算。在某些条件下,正在转换的数据将会振荡并且线程将花费一个多小时来完成。为了比较,大多数线程在一分钟内完成。
已经发现,长时间运行的线程中的数据并不相关。我想打断任何运行时间超过一定时间的线程。最好的方法是什么?
答案 0 :(得分:21)
使用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;
}
答案 1 :(得分:5)
您可以像在其他答案中一样取消未来等,但您需要确保“数字运算”的线程可以处理中断并正常终止。你说这是一个黑盒子操作 - 你是否确定在黑盒子里主动检查线程的中断状态?如果不是,则无法通过中断取消。黑盒子需要记住中断。
答案 2 :(得分:3)
最好的方法是再引入一个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);
}
答案 3 :(得分:0)
您可以获得相应期货的清单(在您提交可赎回时创建的)及其启动时间。
如果某个任务运行超过定义的时间,则另一个任务可以检查每分钟,如果是,则在Future中调用cancel(true)。完成的期货将从名单中删除。
答案 4 :(得分:0)
您可以使用此方法
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
throws InterruptedException
并将最大超时设置为一分钟。如果你的线程占用的数量超过了它,那么它就会被中止。