等待计时器在 Java 中完成

Posted

技术标签:

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

+1。或者,如果由于某种原因必须使用Timer,那么您可以使用 Condition (java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/…) 来同步事件上的两个线程(例如完成计划任务)。 是的,Effective Java(第 2 版)中的第 68 条建议将 ScheduledThreadPoolExecutor 作为 Timer 的更灵活的替代品。 +1 提及这一点,因为要求推荐的做法。 或使用 CountdownLatch 等***.com/questions/289434/…【参考方案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

以上是关于等待计时器在 Java 中完成的主要内容,如果未能解决你的问题,请参考以下文章

Java 并发:倒计时锁存器与循环障碍

javaweb,监听器和定时器(Quartz)互相调控的问题

C# - 如何暂停应用程序直到计时器完成?

在返回位置之前如何等待计时器?

在 C# 中发送 http 请求时,如何设置计时器或等待?

nasm 程序集 linux 计时器或睡眠