Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ScheduledExecutorService启动和停止计时器_Java_Multithreading_Design Patterns_Timer_Executorservice - Fatal编程技术网

Java 使用ScheduledExecutorService启动和停止计时器

Java 使用ScheduledExecutorService启动和停止计时器,java,multithreading,design-patterns,timer,executorservice,Java,Multithreading,Design Patterns,Timer,Executorservice,从我的阅读资料来看,ScheduledExecutorService似乎是Java中启动和停止计时器的正确方法 我需要移植一些启动和停止计时器的代码。这不是周期计时器。此代码在启动计时器之前停止计时器。因此,实际上每次启动都是一次重新启动()。我正在寻找使用ScheduledExecutorService实现这一点的正确方法。这是我想到的。寻找我缺少的东西的评论和见解: ScheduledExecutorService _Timer = Executors.newScheduledThreadP

从我的阅读资料来看,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
}
ScheduledExecutorService\u Timer=Executors.newScheduledThreadPool(1);
ScheduledFuture _TimerFuture=null;
私有布尔startTimer(){
试一试{
如果(_TimerFuture!=null){
//取消执行未来任务(timerptosk())
//如果任务已经在运行,不要中断它。
_TimerFuture.cancel(假);
}
_TimerFuture=_Timer.schedule(新TimerPtask(),
计时器以秒为单位,
时间单位(秒);
返回true;
}捕获(例外e){
返回false;
}
}
私有布尔停止计时器(){
试一试{
如果(_TimerFuture!=null){
//取消执行未来任务(timerptosk())
//如果任务已经在运行,请在此处中断它。
_TimerFuture.cancel(真);
}
返回true;
}捕获(例外e){
返回false;
}
}
私有类TimerPtask实现可运行{
公共无效运行(){
TimerPopped();
}  
}
公共无效时间已映射(){
//做点什么
}
蒂亚,
卢布这看起来是个问题:

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

        _TimerFuture = _Timer.schedule(new TimerPopTask(), 
                                       TIMER_IN_SECONDS, 
                                       TimeUnit.SECONDS);
    // ......
}
由于您要将false传递给cancel,因此如果任务已在运行,则旧的
\u TimerFuture
可能不会被取消。无论如何都会创建一个新的线程池(但它不会并发运行,因为
ExecutorService
的线程池大小固定为1)。在任何情况下,调用startTimer()时,这听起来都不像您希望的重新启动计时器的行为

我会重新建造一点。我将使
timerptosk
实例成为您“取消”的对象,并且在创建
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;
    }
}
然后,我将保留
timerptosk
的实例,而不是
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);
您可能希望使用一种混合的方法,保留对我所描述的当前TimerPtask和当前ScheduledFuture的引用,并尽最大努力取消它并释放线程(如果可能),但要知道它不一定会取消


(注意:这一切都假设startTimer()和stopTimer()方法调用仅限于一个主线程,线程之间只共享
TimerPtask
实例。否则,您将需要额外的保护措施。)

编写的代码不会编译:\u startTimer()中的batchTimer不会在任何地方声明。如果您可以更详细地了解预期行为,这将非常有用:startTimer和stopTimer的返回值是多少?为什么你想让start/stopTimer潜在地阻止呼叫?@Sbodd,当我去启动计时器时,如果已经有计时器在运行,我想停止它,这样我就不会有两个计时器同时弹出。我想我只需要在将来的实例上调用cancel(),而不是get(),这一点很好。让我问你这个,假设一个任务正在运行。将创建一个新任务,并计划在秒后运行计时器。这个时间(计时器以秒为单位)什么时候开始?它是在调用schedule()时立即开始,还是在线程池中有空闲线程时开始?计时器以秒为单位延迟在调用schedule()时立即开始。任务保证不早于延迟开始,但是,它可能晚一些开始(部分取决于线程可用性)。来自javadoc for ScheduledThreadPoolExecutor:“延迟的任务在启用之前执行,但是在启用之后,它们将在何时开始没有任何实时保证。”