3

我有一个表单的处理循环

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()or的结果Thread.interrupted()存储在volatile变量中并且该变量用作while循环测试条件的版本。这只是一种风格还是有必要这样做?在我所写的内容中,我必须担心以某种方式可以清除设置之间的中断标志(无论是在线程处于活动状态时被接收,还是通过我捕获InterruptedException并重新设置标志)和何时Thread.currentThread().isInterrupted()被调用循环测试?

4

3 回答 3

3

你的代码对我来说看起来不错。引入一个额外的 volatile 变量将是不必要的复杂性:中断状态完成了这项工作。

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

于 2012-07-28T06:36:26.113 回答
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);
    }
  }}
于 2012-07-28T08:59:23.413 回答
0

基本上你应该利用java.util.concurrent这里的库。你应该通过提交你的任务ExecutorService.submit()然后调用阻塞方法Future.get(),然后你可以确保这些方法会通过抛出一个来尽快响应中断ExecutionException()。你可能应该摆脱那个线程.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);
    }
  }
}      
于 2012-07-30T06:53:00.593 回答