Почему таймер не работает, если мы не генерируем окно? - PullRequest
3 голосов
/ 19 марта 2010

Вот код:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class TimerSample {
  public static void main(String args[]) {
    new JFrame().setVisible(true);
    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        System.out.println("Hello World Timer");
      }
    };
    Timer timer = new Timer(500, actionListener);
    timer.start();
  }
}

Генерирует окно, а затем периодически печатает «Hello World Timer» в терминале (командная строка). Если я прокомментирую эту строку new JFrame().setVisible(true);, приложение ничего не выводит в командную строку. Почему?

ДОБАВЛЕНО:

Я не уверен, что правильно понимаю ответы. Насколько я понял, таймер запускает новый поток. И этот новый поток существует одновременно с «основным» потоком. Когда «основной» поток завершен (когда все сделано, и больше нечего делать), все приложение завершается (вместе с «новым» потоком, созданным таймером). Правильно?

ДОБАВЛЕНО 2:

Вышеописанное объяснение все еще не объясняет все. Например, программа работает, если я прокомментирую new JFrame().setVisible(true); и поставлю try {Thread.sleep(20000);} catch(InterruptedException e) {}; после timer.start(). Итак, я вроде это понимаю. В спящем режиме мы сохраняем «основной» поток занятым, чтобы созданный таймер поток мог существовать. Но new JFrame().setVisible(true); не занимают "главное". Насколько я понимаю, он создает свой собственный поток (например, таймер). Итак, почему поток JFrame может существовать без основного потока, а поток таймера не может?

Ответы [ 3 ]

5 голосов
/ 19 марта 2010

Вы упускаете суть. Таймер не зависит от окна, которое вы создали, и работает также, когда вы закомментируете эту строку создания окна.

Однако то, что вам не удалось увидеть, так это: ваша основная программа завершает работу после timer.start(), следовательно, выполнение вашей программы прекращается и вместе с этим идет таймер.

Вы можете проверить это, если добавите Thread.sleep(20000); в конце (включая обязательную обработку исключений) или любой другой код, который занимает некоторое время. Тогда ваш таймер работает отлично даже без создания какого-либо окна.

Дело в том, что JFrame, даже когда ничего не отображается, остается активным, что, в свою очередь, поддерживает работу вашего таймера.

1 голос
/ 19 марта 2010

Соответствующий каждому объекту Таймер один фоновый поток, который используется для выполнения всех таймера задачи, последовательно.

После последней живой ссылки на Таймер объекта уходит и все нерешенные задачи выполнены выполнение, выполнение задачи таймера поток завершается изящно (и становится предметом мусора коллекция). Тем не менее, это может занять произвольно долго происходить. По умолчанию, поток выполнения задачи не запускается как нить демона, так он способен держать заявку от терминатор. Если звонящий хочет прекратить выполнение задачи таймера резьба быстро, вызывающий должен вызвать метод отмены таймера. 1

Так какое отношение java.util.Timer имеет к javax.swing.Timer, который вы можете спросить?

В версии 1.3 другой класс Timer был добавлено в платформу Java: java.util.Timer. И это и javax.swing.Timer обеспечивает то же самое базовая функциональность 2

Таким образом, ваша последняя ссылка на таймер исчезнет до того, как ваш таймер действительно запустится ... если вы заметите, что ваш основной метод завершается, как только вы вызовете timer.start();, и если нет чего-то, что сохранит ваш Основной поток активен, пока не запустится таймер, тогда ваш таймер может никогда не запуститься.

В первом примере JFrame поддерживает ваш основной поток живым.

Во втором примере вы спите достаточно долго для запуска timer, а затем таймер заставляет основной поток остаться в живых:

public static void main(String args[]) {
        //new JFrame().setVisible(true);
        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("Hello World Timer");
            }
        };
        Timer timer = new Timer(500, actionListener);
        timer.start();
        try {
            Thread.sleep(500);//<--- the timer will still die
            Thread.sleep(100);//<--- sleep for another 100 and the timer will start printing although you can't rely on it
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
1 голос
/ 19 марта 2010

Функция таймера вызывается в цикле событий окна (где также учитываются такие вещи, как изменение размера, перемещение, перерисовка и т. Д.) Очевидно, что если окно скрыто, цикл обработки событий не выполняется.

Это неправильно, проверьте ответ Фрэнка.

...