Платформа.runLater и задача в JavaFX

я проводил некоторые исследования по этому поводу, но я все еще очень смущен, чтобы сказать меньше.

может ли кто-нибудь дать мне конкретный пример того, когда использовать Task и когда использовать Platform.runLater(Runnable);? Какая разница? Есть ли золотое правило, когда использовать любой из них?

также исправьте меня, если я ошибаюсь, но не являются ли эти два "объекта" способом создания другого потока внутри основного потока в GUI (используется для обновления GUI)?

4 ответов


использовать Platform.runLater(...) для быстрых и простых операций и Task для сложных и больших операций .

пример: почему мы не можем использовать Platform.runLater(...) для длинных вычислений (взятых из Ниже ссылки).

проблема: фоновый поток, который просто считает от 0 до 1 миллиона и обновляет индикатор выполнения в ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС.

код с помощью Platform.runLater(...):

final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
    @Override public void run() {
    for (int i = 1; i <= 1000000; i++) {
        final int counter = i;
        Platform.runLater(new Runnable() {
            @Override public void run() {
                bar.setProgress(counter / 1000000.0);
            }
        });
    }
}).start();

это отвратительный кусок кодекса, преступление против природы (и программирование в целом). Во-первых, вы потеряете клетки мозга, просто глядя в этой двойной вложенности Runnables. Во-вторых, он собирается заболотить очередь событий с маленькими Runnables-миллион из них на самом деле. Ясно, что нам нужен какой-то API, чтобы упростить написание фона работники которые после этого связывают назад с пользовательский интерфейс.

код с помощью задачи:

Task task = new Task<Void>() {
    @Override public Void call() {
        static final int max = 1000000;
        for (int i = 1; i <= max; i++) {
            updateProgress(i, max);
        }
        return null;
    }
};

ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();

он не страдает ни от одного из недостатков, показанных в предыдущем коде

ссылки : рабочий поток в JavaFX 2.0


  • Platform.runLater: Если вам нужно обновить компонент GUI из потока без GUI, вы можете использовать это, чтобы поместить свое обновление в очередь, и оно будет обработано потоком GUI как можно скорее.
  • Task осуществляет Worker интерфейс, который используется, когда вам нужно запустить длинную задачу вне потока GUI (чтобы избежать замораживания вашего приложения), но все равно нужно взаимодействовать с GUI на каком-то этапе.

если вы знакомы с Swing, то бывшее эквивалентно SwingUtilities.invokeLater и последнее к понятию SwingWorker.

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


теперь его можно изменить на лямбда-версию

@Override
public void actionPerformed(ActionEvent e) {
    Platform.runLater(() -> {
        try {
            //an event with a button maybe
            System.out.println("button is clicked");
        } catch (IOException | COSVisitorException ex) {
            Exceptions.printStackTrace(ex);
        }
    });
}

одна причина использовать платформу explicite.runLater () может быть, вы привязали свойство в пользовательском интерфейсе к свойству service (result). Поэтому, если вы обновите свойство связанного сервиса, вы должны сделать это через runLater ():

в потоке пользовательского интерфейса, также известном как поток приложения JavaFX:

...    
listView.itemsProperty().bind(myListService.resultProperty());
...

в реализации службы (фоновый работник):

...
Platform.runLater(() -> result.add("Element " + finalI));
...