我有一个
形式的处理循环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}}时?
答案 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);
}
}
}