在 Java 中等待计时器完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1321620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:14:23  来源:igfitidea点击:

Waiting for a Timer to finish in Java

javasynchronizationtimermonitor

提问by ripper234

I'm using java.util.Timerto schedule a periodic task. At one point, I'd like to shut it down, and wait for it to finish.

我正在使用java.util.Timer来安排定期任务。有一次,我想关闭它,然后等待它完成

Timer.cancel()will prevent any future tasks from running. How do I make sure any tasks are not running at the moment (or wait for them if they are?)

Timer.cancel()将阻止任何未来的任务运行。我如何确保当前没有运行任何任务(或者等待它们?)

I can introduce external synchronization mechanisms, but I don't see how they can cover all cases. For example, if I synchronize on some Monitor within the task, I still miss the case when the task just started executing but didn't take the monitor.

我可以引入外部同步机制,但我看不出它们如何涵盖所有情况。例如,如果我在任务内的某个Monitor上同步,我仍然会错过任务刚开始执行但没有采取monitor的情况。

What is the recommended practice for waiting until all tasks are really done, including currently running tasks?

等待所有任务(包括当前正在运行的任务)真正完成的推荐做法是什么?

采纳答案by Mark

You would be better using an ScheduledExecutorServiceinstead of a Timer to schedule your periodic task. ScheduledExecutorService provides a shutdown() method that will execute any pending tasks. You can then call awaitTermination() to wait for shutdown() to finish.

您最好使用ScheduledExecutorService而不是 Timer 来安排您的定期任务。ScheduledExecutorService 提供了一个 shutdown() 方法来执行任何挂起的任务。然后您可以调用 awaitTermination() 等待 shutdown() 完成。

回答by Keshav

Something like below might help your needs-

像下面这样的东西可能会帮助您的需求-

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