繁体   English   中英

使用ScheduledExecutorService启动和停止计时器

[英]using ScheduledExecutorService to start and stop timer

从我的读数来看,似乎ScheduledExecutorService是在Java中启动和停止计时器的正确方法。

我需要移植一些启动和停止计时器的代码。 这不是周期性计时器。 此代码在启动之前停止计时器。 所以,实际上每次启动都是一次重启()。 我正在寻找使用ScheduledExecutorService执行此操作的正确方法。 这就是我想出的。 寻找有关我缺少的事情的评论和见解:

ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> _TimerFuture = null;

private boolean startTimer() {
    try {
        if (_TimerFuture != null) {
            //cancel execution of the future task (TimerPopTask())
            //If task is already running, do not interrupt it.
            _TimerFuture.cancel(false);
        }

        _TimerFuture = _Timer.schedule(new TimerPopTask(), 
                                       TIMER_IN_SECONDS, 
                                       TimeUnit.SECONDS);
        return true;
    } catch (Exception e) {
        return false;
    }
}

private boolean stopTimer() {
    try {
        if (_TimerFuture != null) {
            //cancel execution of the future task (TimerPopTask())
            //If task is already running, interrupt it here.
            _TimerFuture.cancel(true);
        }

        return true;
    } catch (Exception e) {
        return false;
    }
}

private class TimerPopTask implements Runnable  {  
    public void run ()   {  
        TimerPopped();
    }  
}

public void TimerPopped () {
    //Do Something
}

tia,卢布

这看起来像一个问题:

private boolean startTimer() {
    // ......
        if (_TimerFuture != null) {
            _TimerFuture.cancel(false);
        }

        _TimerFuture = _Timer.schedule(new TimerPopTask(), 
                                       TIMER_IN_SECONDS, 
                                       TimeUnit.SECONDS);
    // ......
}

由于您要传递false以取消,因此如果任务已在运行,则旧的_TimerFuture可能不会被取消。 无论如何都会创建一个新的(但它不会同时运行,因为您的ExecutorService的固定线程池大小为1)。 在任何情况下,这听起来都不像您在调用startTimer()时重新启动计时器所需的行为。

我会重新解构一下。 我会让TimerPopTask实例成为你“取消”的东西,我会在创建后单独保留ScheduledFutures

private class TimerPopTask implements Runnable  {
    //volatile for thread-safety
    private volatile boolean isActive = true;  
    public void run ()   {  
        if (isActive){
            TimerPopped();
        }
    }  
    public void deactivate(){
        isActive = false;
    }
}

那么我会保留TimerPopTask的实例,而不是ScheduledFuture的实例,并重新排列startTimer方法:

private TimerPopTask timerPopTask;

private boolean startTimer() {
    try {
        if (timerPopTask != null) {
            timerPopTask.deactivate();
        }

        timerPopTask = new TimerPopTask();
        _Timer.schedule(timerPopTask, 
                        TIMER_IN_SECONDS, 
                        TimeUnit.SECONDS);
        return true;
    } catch (Exception e) {
        return false;
    }
}

(对stopTimer()方法的类似修改。)

如果您确实需要在当前计时器到期之前“重新启动”计时器,则可能需要增加线程数:

private ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(5);

您可能希望采用混合方法,保持对我所描述的当前TimerPopTask和当前ScheduledFuture的引用,并尽可能取消它并尽可能释放线程,理解它不能保证取消。

(注意:这都假定startTimer()和stopTimer()方法调用仅限于一个主线程,并且只有线程之间共享TimerPopTask实例。否则,您将需要额外的安全措施。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM