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

时间:2013-09-10 02:55:52

标签: java multithreading swing concurrency javafx

我很好奇javafx.concurent和Platform.runLater之间用于多线程JavaFx编程的区别是什么。

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

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

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

1 个答案:

答案 0 :(得分:14)

<强> Platform.runLater

WorkerPlatform.runLater的补充。

  • 在执行JavaFX应用程序线程时使用Platform.runLater,并且您希望在JavaFX应用程序线程上运行某些逻辑。
  • 在JavaFX应用程序线程上运行时使用Worker,并希望在新线程上生成某些逻辑或(尤其)I / O,以免阻止JavaFX申请主题。

您永远不会想要在Platform.runLater的{​​{1}}方法中进行网络I / O,但通常希望在run&#39; s Worker方法。

任务和服务

考虑使用TaskServiceWorker子类。这些是FutureTask的JavaFX包装器(又是Runnable)。 Worker提供了一个call方法来在后台线程上运行逻辑。它们维护执行status(通过线程安全回调通知JavaFX线程以进行状态更改)并通过valuemessageexception属性返回调用结果。

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

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

一起使用Workers和Platform.runLater

此外,使用ServiceTaskService的使用并不矛盾。例如,如果您有一个非常长的运行Platform.runLater,您希望定期将部分结果返回到UI或缓冲区填充,然后在任务{{1}中执行Task方法就是这样做的。

使用现有的线程系统

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

小心编写多线程代码

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

回答您的一些补充问题

  

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

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

  

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

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

参见相关文章,了解为什么有2个或更多&#34;画线&#34;可能是不可取的:

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

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

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

  

重物(例如打开FileChooser)

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