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

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

19
задан Vaibhav Mule 16 April 2015 в 10:26
поделиться

4 ответа

из TimerTask.cancel () :

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

Итак, однажды отменил, он никогда не будет работать снова. Вам все лучше, используя более современную планированиюExecutorservice (от 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);
25
ответ дан 30 November 2019 в 02:18
поделиться

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

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

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

4
ответ дан 30 November 2019 в 02:18
поделиться

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

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

он работает на моей машине:

it works!

4
ответ дан 30 November 2019 в 02:18
поделиться

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

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

В основном существует два метода: Пауза и возобновляется

в паузе:

public void pause() {
    this.timer.cancel();
}

В резюме:

public void resume() {
    this.timer = new Timer();
    this.timer.schedule( aTask, 0, 1000 );
}

, что делает восприятие паузы / резюме.

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

7
ответ дан 30 November 2019 в 02:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: