JavaFX中的Platform.runLater和Task

我一直在做这方面的研究,但我仍然非常困惑,至less可以说。

任何人都可以给我一个具体的例子,何时使用Task ,何时使用Platform.runLater(Runnable); ? 究竟是什么区别? 什么时候使用这些方法是否有一条金科玉律?

还纠正我,如果我错了,但不是这两个“对象”的方式创build另一个线程内的GUI(用于更新graphics用户界面)的主线程?

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

  • Platform.runLater(...)用例
  • Task :Ensemble App中的任务示例的用例

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

问题:后台线程数从0到100万,并在UI中更新进度条。

使用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进行通信。

使用任务代码:

 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的概念。

Task的javadoc给出了许多应该说明如何使用它们的例子。 你也可以参考关于并发的教程 。

现在可以更改为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); } }); } 

使用一个明确的Platform.runLater()的一个原因可能是你绑定了一个属性在ui中的一个服务(result)属性。 所以,如果你更新绑定的服务属性,你必须通过runLater()来做到这一点:

在UI线程中也被称为JavaFX应用程序线程:

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

在服务实施(后台工作):

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