Пауза / остановка и запуск / возобновление 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(); } } 

Итак, мой вопрос: как приостановить timer1 во время работы timer2 и наоборот, пока работает timer2 ? Производительность и сроки – моя главная задача, так как это необходимо реализовать в другом потоке. Кстати, я пытаюсь реализовать эти параллельные таймеры на Android.

Спасибо за вашу помощь!

Solutions Collecting From Web of "Пауза / остановка и запуск / возобновление Java TimerTask непрерывно?"

Из TimerTask.cancel() :

Обратите внимание, что вызов этого метода из метода run задачи повторного таймера абсолютно гарантирует, что задача таймера не будет работать снова.

Поэтому, как только он отменен, он больше никогда не запустится. Вам лучше использовать более современный ScheduledExecutorService (от Java 5+).

Изменить: Базовая конструкция:

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

Но, глядя в него, нет способа отменить эту задачу после ее запуска, не отключая службу, что немного странно.

TimerTask этом случае 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); 

Самое простое решение, которое я нашел: просто добавьте логическое значение в код запуска в задаче таймера, например:

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

Если вы уже отменили один таймер, вы не можете его повторно запустить, вам нужно будет создать новый.

См. Этот ответ , он содержит видео и исходный код, как я сделал что-то подобное.

В принципе есть два метода: 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 . Это немного сложнее, но давайте делать крутые анимации, позволяя рисовать определенный компонент с разной скоростью (вместо того, чтобы быть линейным)

Пересмотрев исходный код, вот изменения (которые в значительной степени подтверждают мой предыдущий ответ)

В задаче 1:

 // Stop timer1 and start timer2 timer1.cancel(); timer2 = new Timer(); // <-- just insert this line timer2.scheduleAtFixedRate(new Task2(), 0, 1000); 

И в задаче2:

 // 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

На мой взгляд, это несколько ошибочно. Если вашему коду требуются временные гарантии, вы не можете использовать Таймер в любом случае, и вы не хотите. «Этот класс не предлагает гарантии в реальном времени: он планирует задачи с использованием метода Object.wait (long)».

Ответ IMHO заключается в том, что вы не хотите приостанавливать и перезапускать таймеры. Вы просто хотите подавить свои методы запуска от своего бизнеса. И это легко: вы просто завертываете их в оператор if . Коммутатор включен, они работают, выключатель выключен, они пропускают этот цикл.

Изменить: вопрос существенно изменился с того, что было изначально, но я оставлю этот ответ, если он поможет кому-либо. Я хочу сказать: если вам неинтересно, когда ваше событие срабатывает в течение N миллисекундного промежутка (просто, чтобы он не превышал один раз каждые N миллисекунд), вы можете просто использовать условные обозначения для методов запуска. Это, по сути, очень распространенный случай, особенно когда N меньше 1 секунды.

Android не будет повторно использовать TimerTask, который уже был запланирован один раз. Поэтому необходимо восстановить как Таймер, так и 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; }