定时器:取消正在运行的任务
问题描述:
我需要创建异步线程,运行一次,延迟时间为2分钟,可以在任何时刻终止。我看见几个可能的解决方案:定时器:取消正在运行的任务
-
ScheduledExecutorService
和FutureTask
让我中断正在运行的任务,但我将不得不调用shutdown()
终止所有正在运行的线程,这将阻止用户直到进程被终止。此外,我将不得不经常调用Thread.interrupted()
,如Enno Shioji's answer中所述。 -
Timer
和TimerTask
不需要释放运行的线程,但我没有办法打断一个正在运行的计时器线程(Timer.cancel()
刚刚取消的未来计划) - 使用Thread and sleep与thread interruption问题。
有没有很好的解决方案? (我使用Tomcat 7)
谢谢
答
一些试验和研究后,FutureTask.cancel()和线程需要中断的类似处理,如Enno Shioji's answer
- 检查中断标志在你的逻辑
- 法追访时表示例外
例子tes TS中断标志:
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,您可以使用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");
}
答
您的方案2的TimerTask,为什么不从run()方法返回调用this.cancel后( )?
这是我写的东西的片段。每当工具遇到会导致进一步执行无效的情况时(例如错误配置),我都会使用相同的技术。
...
if (count < 1) {
logger.error("CANCELING THREAD FOR " + host + ":" + jmxPort + "! " +
"- CONFIGURATION INCOMPLETE - DUMP_COUNT must be 1 or greater.");
this.cancel();
return;
}
...
没错,但有两个缺点。首先,如果我在线程中启动一个长进程,我必须不断地引用isInterrupted标志;第二,我必须调用shutdown来释放正在运行的线程,这将阻塞用户,直到线程运行完毕 – lili 2012-03-28 19:27:09
ExecutorService返回的FutureTask将您抽象为使用线程。按照JavaDoc,如果您为mayInterruptIfRunning传递true,它将负责中断工作线程。 – 2012-03-28 19:34:45
不完全是根据恩诺盐路的回答是:http://*.com/questions/2903342/why-thread-started-by-scheduledexecutorservice-schedule-never-quits – lili 2012-03-28 19:36:09