暂停/停止并继续启动/恢复Java TimerTask?
我有一个关于Java TimerTask的简单问题。 如何根据一定的条件暂停/恢复两个TimerTask任务? 例如,我有两个在彼此之间运行的定时器。 当第一个定时器的任务内部满足一定的条件时,第一个定时器停止并启动第二个定时器,在第二个定时器的任务内满足一定的条件时也会发生同样的情况。 下面的课程显示了我的意思:
public class TimerTest { Timer timer1; Timer timer2; volatile boolean a = false; public TimerTest() { timer1 = new Timer(); timer2 = new Timer(); } public void runStart() { timer1.scheduleAtFixedRate(new Task1(), 0, 1000); } class Task1 extends TimerTask { public void run() { System.out.println("Checking a"); a = SomeClass.getSomeStaticValue(); if (a) { // Pause/stop timer1, start/resume timer2 for 5 seconds timer2.schedule(new Task2(), 5000); } } } class Task2 extends TimerTask{ public void run() { System.out.println("Checking a"); a = SomeClass.getSomeStaticValue(); if (!a) { // Pause/stop timer2, back to timer1 timer1.scheduleAtFixedRate(new Task1(), 0, 1000); } // Do something... } } public static void main(String args[]) { TimerTest tt = new TimerTest(); tt.runStart(); } }
所以我的问题是,当timer2
运行时,如何在运行timer2
暂停timer1
,反之亦然? 性能和时间是我主要关心的,因为这需要在另一个正在运行的线程中实现。 顺便说一下,我试图在Android上实现这些并发计时器。
谢谢你的帮助!
从TimerTask.cancel()
:
请注意,从重复计时器任务的run方法内调用此方法绝对保证计时器任务不会再次运行。
所以一旦取消,它不会再运行。 你会更好,而不是使用更现代的ScheduledExecutorService
(从Java 5+)。
编辑:基本构造是:
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); exec.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);
但考虑到这一点,没有办法取消这个任务一旦开始,而不closures服务,这有点奇怪。
在这种情况下TimerTask
可能更容易,但是当你启动一个时,你需要创build一个新的实例。 它不能被重复使用。
或者,您可以将每个任务封装为单独的瞬态服务:
final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); Runnable task1 = new Runnable() { public void run() { a++; if (a == 3) { exec.shutdown(); exec = Executors.newSingleThreadScheduledExecutor(); exec.scheduleAtFixedRate(task2, 0, 1000, TimeUnit.MILLISECONDS) } } }; exec.scheduleAtFixedRate(task1, 0, 1000, TimeUnit.MILLISECONDS);
我发现最简单的解决scheme:只需在计时器任务的运行代码中添加一个布尔值,如下所示:
timer.schedule( new TimerTask() { public void run() { if(!paused){ //do your thing } } }, 0, 1000 );
如果你已经取消了一个定时器,你不能重新启动它,你将不得不创build一个新的定时器。
看到这个答案 ,它包含一个video和源代码,我是如何做类似的。
基本上有两种方法: pause
和resume
暂停:
public void pause() { this.timer.cancel(); }
简历中:
public void resume() { this.timer = new Timer(); this.timer.schedule( aTask, 0, 1000 ); }
这使得停顿/恢复的感觉。
如果您的定时器根据应用程序的状态执行不同的操作,则可以考虑使用StatePattern
拳头定义一个抽象的状态:
abstract class TaskState { public void run(); public TaskState next(); }
并提供尽可能多的状态,只要你喜欢。 关键是一个国家把你引向另一个国家。
class InitialState extends TaskState { public void run() { System.out.println( "starting..."); } public TaskState next() { return new FinalState(); } } class FinalState extends TaskState { public void run() { System.out.println("Finishing..."); } public TaskState next(){ return new InitialState(); } }
然后你改变你的计时器的状态。
Timer timer = new Timer(); TaskState state = new InitialState(); timer.schedule( new TimerTask() { public void run() { this.state.run(); if( shouldChangeState() ) { this.state = this.state.next(); } } }, 0, 1000 );
最后,如果你需要的是执行同样的事情,但速度不同,你可以考虑使用TimingFramework 。 这是一个更复杂一点,但让你做很酷的animation,允许某些组件的绘画发生在不同的速度(而不是线性)
回顾你的源代码,这里是更改(这几乎证实我以前的答案)
在task1中:
// Stop timer1 and start timer2 timer1.cancel(); timer2 = new Timer(); // <-- just insert this line timer2.scheduleAtFixedRate(new Task2(), 0, 1000);
在task2中:
// Stop timer2 and start timer1 timer2.cancel(); timer1 = new Timer(); // <-- just insert this other timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
它运行在我的机器上:
有用! http://img687.imageshack.us/img687/9954/capturadepantalla201001m.png
在我看来,这是有些误导。 如果你的代码需要时间保证,你不能使用Timer,也不想。 “这个类不提供实时保证:它使用Object.wait(long)方法来调度任务。”
恕我直言,答案是你不想暂停和重新启动定时器。 你只是想压制他们的运行方式做生意。 这很容易:你只是把它们包装在一个if
语句中。 开关打开,他们运行,开关closures,他们错过了这个周期。
编辑:问题已经从原来的大幅转移,但我会离开这个答案,以防万一它帮助任何人。 我的观点是:如果你不关心你的事件在N毫秒范围内触发(只是每N毫秒不超过一次),你可以在运行方法上使用条件。 事实上,这是一个很常见的情况,特别是当N小于1秒时。
Android将不会重复使用已经安排过的TimerTask。 所以有必要重新实例化Timer和TimerTask,例如像这样在一个片段中:
private Timer timer; private TimerTask timerTask; public void onResume () { super.onResume(); timer = new Timer(); timerTask = new MyTimerTask(); timer.schedule(timerTask, 0, 1000); } public void onPause () { super.onPause(); timer.cancel(); // Renders Timer unusable for further schedule() calls. }
我能够使用以下代码停止计时器和任务:
if(null != timer) { timer.cancel(); Log.i(LOG_TAG,"Number of cancelled tasks purged: " + timer.purge()); timer = null; } if(task != null) { Log.i(LOG_TAG,"Tracking cancellation status: " + task.cancel()); task = null; }