我需要创建一个延迟2分钟运行一次的异步线程,并且可以随时终止。我看到了几种可能的解决方案:
ScheduledExecutorService
和FutureTask
允许我中断正在运行的任务,但我必须调用shutdown()
来终止所有正在运行的线程,这将阻止用户,直到进程终止。另外,我必须经常按Enno Shioji's answer。Thread.interrupted()
Timer
和TimerTask
不需要释放正在运行的线程,但我无法中断正在运行的计时器线程(Timer.cancel()
只是取消将来的计划)有一个很好的解决方案吗? (我正在使用tomcat 7)
谢谢
答案 0 :(得分:1)
经过一些测试和研究后,FutureTask.cancel()和Threads需要类似的中断处理,如Enno Shioji's answer中所述
- 检查逻辑中的中断标志
- 根据中断异常行事
醇>
测试中断标志的示例:
private final class MyTask implements Runnable {
public void run() {
try{
for(int j=0; j<100000000; j++) {
for(int i=1; i<1000000000; i++){
if(Thread.interrupted()){ //Don't use Thread.interrupt()!
Log.debug("Thread was interrupted for" + cache);
return; //Stop doing what you are doing and terminate.
}
Math.asin(0.1565365897770/i);
Math.tan(0.4567894289/i);
}
}
}catch(Throwable e){//if exception is uncaught, the scheduler may not run again
...
}
}
}
据我了解,当应用程序结束运行时,ScheduledExecutorService
可能是shutdown
答案 1 :(得分:1)
对于使用TimerTask的方案2,为什么不在调用this.cancel()后从run()方法返回?
这是我写的东西的片段。每当工具遇到导致进一步执行无效的情况时,我都会使用相同的技术,例如配置错误。
...
if ( count < 1 ) {
logger.error("CANCELING THREAD FOR " + host + ":" + jmxPort + "! " +
"- CONFIGURATION INCOMPLETE - DUMP_COUNT must be 1 or greater.");
this.cancel();
return;
}
...
答案 2 :(得分:0)
使用选项1,您可以FutureTask.cancel()使用mayInterruptIfRunning
参数设置为true
取消您的任务。
ScheduledExecutorService.scheduleAtFixedRate()创建了ScheduledFuture,仍然可以通过FutureTask api取消。
这是我用来验证任务被取消的天真测试。我想如果你做一些阻塞IO(网络或磁盘),工作线程可能不会被中断,但我还没有测试过它。如果在任务未运行时调用cancel,则它都会很好地停止,但如果在调用cancel时任务正在运行,则执行程序将尝试终止该线程。
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new Runnable() {
int i = 0;
public void run() {
int j = i++;
System.err.println("Run " + j);
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
System.err.println("Interrupted " + j);
}
}
}, 1000L, 2000L, TimeUnit.MILLISECONDS);
Thread.sleep(10000L);
System.err.println("Canceled " + future.cancel(true));
Thread.sleep(20000L);
executor.shutdownNow();
System.err.println("Finished");
}