【问题标题】:Waiting for a Timer to finish in Java等待计时器在 Java 中完成
【发布时间】:2010-11-22 05:44:30
【问题描述】:

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

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

我可以引入外部同步机制,但我看不出它们如何涵盖所有情况。例如,如果我在任务中的某个监视器上进行同步,我仍然会错过任务刚开始执行但没有占用监视器的情况。

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

【问题讨论】:

    标签: java synchronization timer monitor


    【解决方案1】:

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

    【讨论】:

    【解决方案2】:

    以下内容可能对您的需求有所帮助-

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

    【讨论】:

    • 你应该使用Thread.sleep(...)而不是Thread.currentThread().sleep(...),因为它是一个静态方法;您的代码可能会诱使您执行someOtherThread.sleep(...) 不休眠someOtherThread
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    相关资源
    最近更新 更多