Javafx:javafx.concurent和Platform.runLater之间的区别?

我很好奇javafx.concurent和Platform.runLater之间在multithreadingJavaFx编程方面究竟有什么区别。

这是否意味着使用javafx.concurrent,我们可以拥有多个实际的绘图线程,或者它们最终都会在一个线程上结束?

我喜欢的一件事是使用JavafX并同时摆动,因为它们都使用了2个不同的绘图线程。 我会使用swing来处理繁重的内容(例如打开FileChooser)并使用JavaFX作为核心可视化内容,例如播放无缝的循环video。 然而,由于无头的exception错误,mac使得这一切变得不可能,所以一切都落在javafx上,这意味着在打开文件追踪器等事情时会有很多停顿。

如果我使用javafx.concurrent重写我的应用程序,我是否可以像使用Swing + JavaFX那样模仿2绘制线程体验?

Platform.runLater

WorkerPlatform.runLater补充。

  • 在执行JavaFX应用程序线程并且希望在JavaFX应用程序线程上运行某些逻辑时,请使用Platform.runLater
  • 在JavaFX应用程序线程上运行时使用Worker ,并希望在新线程上生成一些逻辑或(特别是)I / O,这样就不会阻止JavaFX应用程序线程。

你永远不会想在Platform.runLaterrun方法中做网络I / O,但是经常想在Workercall方法中做。

任务和服务

考虑使用Worker的Task或Service子类。 这些是FutureTask的 JavaFX包装器(后者又是Runnable )。 Workers提供了一种调用方法来在后台线程上运行逻辑。 它们维护执行状态 (通过线程安全回调通知JavaFX线程以进行状态更改)并通过值 , 消息和exception属性返回调用结果。

利用TaskService javadoc示例中的设计模式,通过以下function简化线程安全应用程序的创建:

  • 用于UI更新的异步数据提取。
  • 任务进度的定期消息更新。
  • 构造尚未附加到显示场景的节点图。
  • 通过进度条等监控进度

一起使用Workers和Platform.runLater

此外,使用TaskService与使用Platform.runLater不兼容。 例如,如果您有一个非常长的运行Task ,您希望定期将部分结果返回到UI或缓冲区填充,那么在任务的call方法中执行Platform.runLater就是这样做的方法。

使用现有的线程系统

当您没有库提供的现有线程服务时,工作人员很有用,而是创建自己的线程以在后台执行。 如果您有现有的线程服务,那么您将需要使用Platform.runLater在JavaFX应用程序线程上执行逻辑。

小心编写multithreading代码

请注意,即使您使用Worker ,您仍需要知道自己在做什么。 您仍然必须注意不要违反标准的JavaFX并发规则,例如永远不更新活动场景图上的节点(包括不更新活动场景图中的节点绑定的值 – 例如可观察的项目列表支持一个ListView )。

回答你的一些补充问题

这是否意味着使用javafx.concurrent,我们可以拥有多个实际的绘图线程,或者它们最终都会在一个线程上结束?

JavaFX中只有一个渲染线程。 您无法使用JavaFX并发制作更多渲染线程。 您可以执行诸如从JavaFX线程创建节点或使用许multithreading将像素设置为关闭屏幕WriteableImage或Canvas,但最终每个渲染操作都通过由您无法控制的JavaFX系统管理的单个线程。

如果我使用javafx.concurrent重写我的应用程序,我是否可以像使用Swing + JavaFX那样模仿2绘制线程体验?

不,即使你可以,我也不认为这是可取的。 使用这样的模型,很容易创建微妙的,难以调试的线程处理相关错误。 您可能从这样的设置中看到的收益可能比您希望或期望的要少。

请参阅相关文章,了解为什么有2个或更多“画线”可能是不可取的:

  • Threadaches
  • multithreading工具包:失败的梦想

Java 8正在添加一个实验性命令行开关,以便为JavaFX应用程序线程和Swing事件调度线程使用相同的线程。 其主要原因是它简化了编程模型。

一切都落在javafx上,这意味着在打开文件追踪器等事情时会有很多停顿。

也许您的代码中存在效率低下(例如在UI线程上执行I / O)导致暂停。

沉重的东西(例如打开FileChooser)

打开和渲染FileChooser并不重要。 JavaFX可以轻松处理此类操作,而不会降低性能。 可能耗费时间的是与I / O相关的东西,例如递归地走大文件树以获取文件属性。 在这种情况下你可以做的是为I / O在Worker运行它生成一个线程,并通过Platform.runLater定期将部分结果反馈给UI线程。 这样的计划将运作良好。 瓶颈不是绘图,因此使用另一个绘图线程没有任何优势。 瓶颈是缓慢的I / O系统,并且通过为I / O使用单独的线程来缓解这一瓶颈,以便主UI线程不受影响,并且用户在I / O发生时不会遇到UI冻结。