正确编写ExecutorService.shutdownNow()可以停止的任务?

时间:2012-07-28 03:31:45

标签: java multithreading concurrency java.util.concurrent

我有一个

形式的处理循环
while (true) {
    doWork();
    Thread.sleep(SLEEP_INTERVAL);
}

我希望从中Runnable制作ExecutorService,与ExecutorService.shutdownNow()配合使用,并在调用public WorkerTask implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { doWork(); try { Thread.sleep(SLEEP_INTERVAL); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } 时退出。

我想这样写:

ExecutorService

简单的测试表明它至少看起来有效,因为任务被中断并将退出,doWork()将关闭,并且在sleep正在处理或在doWork()期间。 (通过改变SLEEP_INTERVAL的工作量和Thread.interrupted()的大小,我几乎可以控制中断发生的位置。

但是当我谷歌时,我会看到使用Thread.currentThread().isInterrupted()Thread.currentThread().isInterrupted()的示例。我明白前者会在后者离开的时候清除中断的旗帜,但我还需要关注其他任何不同吗?

我还看到Thread.interrupted()volatile的结果存储在while变量中的版本,该变量用作InterruptedException循环测试条件。这只是一种风格还是需要这样做?在我写的内容中,我不得不担心某些事情可以清除设置时的中断标志(无论是在线程处于活动状态时接收,还是通过我的捕获Thread.currentThread().isInterrupted()并重新置位标志)和在循环测试中调用{{1}}时?

3 个答案:

答案 0 :(得分:3)

您的代码对我来说很好。引入额外的volatile变量将是不必要的复杂性:中断状态可以完成工作。

Java Concurrency in Practice 中推荐的处理任务中断的方法是抛出InterruptedException(如果任务是Callable,这是可行的而不是Runnable),或确保设置中断状态并尽快退出任务。你的代码做得很好。

答案 1 :(得分:0)

如果符合您的要求,您可以查看ScheduledExecutorService

 class BeeperControl {
    private final ScheduledExecutorService scheduler =
      Executors.newScheduledThreadPool(1);

    public void beepForAnHour() {
      final Runnable beeper = new Runnable() {
        public void run() { System.out.println("beep"); }
      };
      final ScheduledFuture<?> beeperHandle =
        scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
      scheduler.schedule(new Runnable() {
        public void run() { beeperHandle.cancel(true); }
      }, 60 * 60, SECONDS);
    }
  }}

答案 2 :(得分:0)

基本上你应该在这里利用java.util.concurrent库。你应该通过ExecutorService.submit()提交任务,然后调用Future.get()之类的阻止方法,然后你可以确定这些方法会响应通过抛出ExecutionException()来尽快中断。你可能应该摆脱Thread.sleep(),因为它什么都不做。您希望尽快嗅探中断。您可能还想等待超时,以防您的任务无限期地执行。因此,如果任务以TimeOutException终止,则任务将通过其Future取消。 我无条件地呼叫cancel(),因为取消已完成的任务无效。 在这种情况下,你可以做一些事情:

 public static void main(String[] args) {
    WorkerTask runnable;
    TimeUnit unit;
    Future<?>   task = executor.submit(workerTask);
    try{
      task.get(timeout,unit);
    } catch(TimeoutException e){

    }catch(ExecutionException e){
        throw e.getCause();  
    } finally{
      //Harmless if the task already completed
      task.cancel(true);
    }
  }
}