从我的读数来看,似乎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, 卢布
答案 0 :(得分:3)
这看起来像一个问题:
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
的实例,而不是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;
}
}
的实例,并重新安排startTimer方法:
private ScheduledExecutorService _Timer = Executors.newScheduledThreadPool(5);
(对stopTimer()方法的类似修改。)
如果你真的希望在当前计时器到期之前需要“重启”计时器,你可能想要提高线程数:
TimerPopTask
您可能想要去的混合方式,保持引用到双方当前TimerPopTask为我描述,也对当前ScheduledFuture,并取消它并释放线程,如果可能最好的努力,理解,它不能保证取消。
(注意:这一切都假定startTimer所()和stopTimer()方法调用被限制在一个单一的主线程,并且只有{{1}}实例线程之间共享否则就需要额外的保护措施。)< / p>