我正在使用java.util.Timer来安排定期任务。有一次,我想关闭它,等待它完成。
Timer.cancel()将阻止任何未来的任务运行。我如何确保当前没有任何任务正在运行(或等待它们?)
我可以引入外部同步机制,但我看不出它们如何涵盖所有情况。例如,如果我在任务中的某个监视器上进行同步,我仍然会错过任务刚刚开始执行但没有使用监视器的情况。
等待所有任务真正完成的建议做法是什么,包括当前正在运行的任务?
答案 0 :(得分:21)
您最好使用ScheduledExecutorService代替计时器来安排定期任务。 ScheduledExecutorService提供了一个shutdown()方法,该方法将执行任何挂起的任务。然后,您可以调用awaitTermination()以等待shutdown()完成。
答案 1 :(得分:0)
下面的内容可能有助于您的需求 -
import java.util.Timer;
import java.util.TimerTask;
public class TimerGracefulShutdown {
public static void main(String[] args) throws InterruptedException {
//This is a synchronization helper class
SyncHelper syncHelper = new SyncHelper();
TimerManager myTimerManager = new TimerManager(syncHelper);
//Try stopping timer after 5 seconds (it wont stop until the 30 seconds sleep of timertask does not finish)
Thread.currentThread().sleep(5000);
System.out.println("Going to stop my timer now");
myTimerManager.stopTimer();
System.out.println("Cancelled timer");
}
}
class TimerManager {
SyncHelper syncHelper;
Timer timer;
public TimerManager(SyncHelper syncHelper) {
this.syncHelper = syncHelper;
startTimer();
}
private void startTimer() {
timer = new Timer(true);
TimerTask myTask = new MyTimerTask(syncHelper);
timer.scheduleAtFixedRate(myTask, 0, 100000);
}
public void stopTimer() {
try {
syncHelper.testAndSetOrReset("acquire");
} catch(Exception e) {
e.printStackTrace();
}
//Shutdown the timer here since you know that your timertask is not executing right now.
timer.cancel();
try {
syncHelper.testAndSetOrReset("release");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyTimerTask extends TimerTask {
private SyncHelper syncHelper;
public MyTimerTask(SyncHelper syncHelper) {
this.syncHelper = syncHelper;
}
public void run() {
try {
syncHelper.testAndSetOrReset("acquire");
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("Over here");
try {
Thread.currentThread().sleep(30000);
} catch(Exception e) {
}
System.out.println("Done sleeping");
//Finally release the helper.
try {
syncHelper.testAndSetOrReset("release");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class SyncHelper {
private int index = 0;
public synchronized void testAndSetOrReset(String command) throws Exception {
if("acquire".equals(command)) {
if(index == 1) {
wait();
}
index++;
} else if("release".equals(command)) {
index--;
notifyAll();
}
}
}