首页 文章

JavaFX中的Platform.runLater和Task

提问于
浏览
67

我一直在研究这个问题,但至少我还是很困惑 .

任何人都可以给我一个具体的例子,说明何时使用 Task 以及何时使用 Platform.runLater(Runnable); ?究竟有什么区别?什么时候使用其中任何一个是否有黄金法则?

如果我错了也不纠正我,但是这两个“对象”是一种在GUI中用于更新GUI的主线程内创建另一个线程的方法吗?

4 回答

  • 2

    使用 Platform.runLater(...) 进行快速简单的操作,使用 Task 进行复杂和大型操作 .

    示例:为什么我们不能使用 Platform.runLater(...) 进行长时间计算(取自下面的参考) .

    问题:后台线程只需0到100万,并在UI中更新进度条 .

    Code using 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来更容易编写后台工作程序,然后与UI进行通信 .

    Code using Task :

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

    它没有上一个代码中显示的任何缺陷

    Reference : Worker Threading in JavaFX 2.0

  • 9
    • Platform.runLater :如果需要从非GUI线程更新GUI组件,可以使用它来将更新放入队列中,并尽快由GUI线程处理 .

    • Task 实现 Worker 接口,当您需要在GUI线程外运行长任务(以避免冻结您的应用程序)时使用该接口,但仍需要在某个阶段与GUI交互 .

    如果你熟悉Swing,前者相当于 SwingUtilities.invokeLater ,后者相当于 SwingWorker 的概念 .

    javadoc of Task给出了很多例子,应该说明如何使用它们 . 您也可以参考the tutorial on concurrency .

  • 84

    它现在可以更改为lambda版本

    @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);
            }
        });
    }
    
  • 49

    使用explicite Platform.runLater()的一个原因可能是您将ui中的属性绑定到service(result)属性 . 因此,如果更新绑定服务属性,则必须通过runLater()执行此操作:

    在UI线程中也称为JavaFX Application线程:

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

    在服务实现(后台工作者):

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

相关问题