定时器:取消正在运行的任务

时间:2012-03-28 19:10:49

标签: java timer tomcat7 scheduled-tasks

我需要创建一个延迟2分钟运行一次的异步线程,并且可以随时终止。我看到了几种可能的解决方案:

  1. ScheduledExecutorServiceFutureTask允许我中断正在运行的任务,但我必须调用shutdown()来终止所有正在运行的线程,这将阻止用户,直到进程终止。另外,我必须经常按Enno Shioji's answer
  2. 中的说明调用Thread.interrupted()
  3. TimerTimerTask不需要释放正在运行的线程,但我无法中断正在运行的计时器线程(Timer.cancel()只是取消将来的计划)
  4. Thread and sleep问题与thread interruption一起使用。
  5. 有一个很好的解决方案吗? (我正在使用tomcat 7)

    谢谢

3 个答案:

答案 0 :(得分:1)

经过一些测试和研究后,FutureTask.cancel()和Threads需要类似的中断处理,如Enno Shioji's answer中所述

  
      
  1. 检查逻辑中的中断标志
  2.   
  3. 根据中断异常行事
  4.   

测试中断标志的示例:

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");
}