В чем разница между временной шкалой и темой в java - PullRequest
4 голосов
/ 28 апреля 2020

Следующие два простых фрагмента делают то же самое, печатая "Hello, world" каждую секунду. Но в чем разница между ними? Когда я должен использовать поток и когда я должен использовать Timeline. Временная шкала внутренне запускает поток? если это не так, как печать выполняется каждую секунду без блокировки основного потока?

Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), e -> System.out.println("Hello, world")));
timeline.setCycleCount(-1);
timeline.play();
new Thread(() -> {
    while (true) {
        System.out.println("Hello, world!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}).start();

И, во втором фрагменте, если я делаю Thread.sleep(some_volatile_variable_of_main_thread_that_changes_overtime), как я могу добиться та же функциональность, используя Timeline.

Ответы [ 2 ]

3 голосов
/ 29 апреля 2020

Чтобы понять разницу, вам нужно подумать о двух основных вопросах:

  • Когда мы используем отдельный Thread, можем ли мы обновить элементы управления пользовательского интерфейса JavaFX из того же потока?
  • Учитывая WritableValue, как мы можем заставить Thread изменить это значение с течением времени с заданной скоростью, начальным значением и конечным значением?

Из документации Timeline :

Временная шкала может использоваться для определения анимации произвольной формы любого WritableValue, например всех свойств JavaFX. Временная шкала, определяемая одним или несколькими ключевыми кадрами, обрабатывает отдельные ключевые кадры последовательно в порядке, указанном в KeyFrame.time. Анимированные свойства, определенные как значения ключа в KeyFrame.values, интерполируются в / из целевых значений ключа в указанное время ключевого кадра в начальную позицию временной шкалы, в зависимости от направления временной шкалы.

Пример: Отскок мяча 14 раз (каждый отскок занимает 3 секунды)

Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(3),
    new KeyValue(ball.layoutXProperty(), parentPane.getBoundsInLocal().getMaxX() - ball.getRadius())));
timeline.setCycleCount(14);
timeline.play();

В итоге, Timeline был разработан для поддержки Animation путем последовательной обработки одного или нескольких KeyFrame s в потоке JavaFX.

  • Когда мне следует использовать поток и когда следует использовать временную шкалу?

Timeline следует использовать для анимации и обновления доступных для записи значений пользовательского интерфейса по ставке. Thread, с другой стороны, следует использовать для выполнения длинных фоновых задач (ExecutorService - всегда лучшая идея).

  • Внутренняя ли временная шкала запускает поток?

Нет, Timeline не запускает новые потоки, он использует поток JavaFX.

  • Последняя часть не совсем то, для чего Timeline был разработан. Если вам нужно изменить продолжительность, вам нужно повторно инициализировать Timeline или удалить старый KeyFrame и добавить новый с новой продолжительностью.
3 голосов
/ 29 апреля 2020

Класс Thread является частью стандартного Java API и представляет фоновый поток. Когда запускается Thread, код либо его Runnable метода *1003*, либо его собственного run метода выполняется по существу параллельно с другими запущенными потоками. Это позволяет коду, выполнение которого может занять много времени, без задержки другого кода, который может быть запущен «одновременно». Программисту стоит использовать это так, что следует соблюдать особую осторожность, если данные распределяются между различными потоками, чтобы гарантировать, что они считываются в согласованном состоянии в любом отдельном потоке, и что данные являются «живыми»: то есть эти изменения данные, сделанные в одном потоке, фактически наблюдаются в других потоках.

В отличие от этого, Timeline является частью инфраструктуры JavaFX и, в частности, частью его API анимации. При запуске приложения JavaFX запускается поток, называемый потоком приложения FX. Этот поток выполняется в al oop и отвечает за отображение пользовательского интерфейса и обработку пользовательских событий (среди прочего). Визуализация пользовательского интерфейса происходит по «импульсу», который (в текущей версии) предназначен для выполнения 60 раз в секунду. Из-за проблем синхронизации данных, упомянутых выше, все изменения в пользовательском интерфейсе должны быть внесены в поток приложения FX. Кроме того, код в потоке приложения FX не должен быть длительным (поэтому он не может делать паузу с sleep() или читать большие наборы данных через IO), потому что он заблокирует поток от рендеринга пользовательского интерфейса.

A Timeline работает с набором KeyFrame s, каждый из которых указывает время (в форме Duration, измеренное с начала временной шкалы) и обработчик события и / или KeyValue. На каждом импульсе потока приложения FX, если работает Timeline, поток приложения FX l oop будет проверять, пора ли запускать какие-либо обработчики событий. Для KeyValue с, если значение является интерполируемым (например, является цифрой c или реализует Interpolatable, его значение будет рассчитываться путем вычисления времени, прошедшего как доля времени для следующего KeyFrame.

Timeline s полезны для простых анимаций (например, перемещая узел по панели, используя KeyValue s, которые определяют его расположение или координаты перевода, или аналогичные), а также для выполнения дискретного набор обновлений пользовательского интерфейса в определенные моменты времени c (например, отображение и скрытие изображений в «памяти»).

Следовательно:

  • Код в обработчиках событий для KeyFrame прикрепленный к Timeline может обновить пользовательский интерфейс, поскольку он гарантированно будет выполняться в потоке приложений FX
  • KeyValue s, которые обновляются как часть KeyFrame в Timeline. свойства элементов пользовательского интерфейса, отображаемых на экране
  • Код в обработчиках событий для KeyFrame s не должен блокировать выполнение или выполнять длительные задачи
  • Попытка использовать Timeline в не-JavaFX-приложение (т.е. где среда выполнения JavaFX не была запущена) завершится сбоем, поскольку не будет потока приложений JavaFX для выполнения обновлений.

И наоборот:

  • Код, выполняемый на background Thread не должен обновлять элементы пользовательского интерфейса (или их свойства). Это верно как для JavaFX, так и для Java Swing / AWT
  • Код, выполняемый в фоновом потоке, может блокировать или выполнять долгосрочные задачи

Обратите внимание, что java.util.Timer и это связанный TimerTask (который является частью стандартного Java API) выполнения в фоновом потоке, созданном внутри Timer. Это означает, что хотя API Timer и TimerTask выглядят несколько похожими на Timeline, они должны подчиняться правилам фоновых потоков (не должны обновлять пользовательский интерфейс и т. Д. c).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...