持续暂停/停止和启动/恢复 Java 计时器任务?

我有一个关于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();      
    }
}

所以我的问题是,我如何在跑步时暂停,反之亦然?性能和时序是我主要关心的问题,因为这需要在另一个正在运行的线程中实现。顺便说一句,我正在尝试在Android上实现这些并发计时器。timer1timer2timer2

感谢您的帮助!


答案 1

From TimerTask.cancel()

请注意,从重复计时器任务的 run 方法中调用此方法绝对可以保证计时器任务不会再次运行。

因此,一旦取消,它就不会再运行了。你最好使用更现代的 ScheduledExecutorService(来自 Java 5+)。

编辑:基本结构是:

ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);

但是仔细研究它,一旦启动就无法取消该任务而不关闭服务,这有点奇怪。

TimerTask在这种情况下可能会更容易,但您需要在启动一个新实例时创建一个新实例。它不能重复使用。

或者,您可以将每个任务封装为单独的瞬态服务:

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);

答案 2

我发现的最简单的解决方案是:只需在计时器任务的运行代码中添加一个布尔值,如下所示:

timer.schedule( new TimerTask() {
    public void run() {
       if(!paused){
           //do your thing
       }
    }
 }, 0, 1000 );

推荐