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

Gls*_*nna 3 java concurrency swing multithreading javafx

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

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

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

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

jew*_*sea 14

Platform.runLater

A Worker是互补的Platform.runLater.

  • 使用Platform.runLater时,您正在执行关闭了JavaFX应用程序线程,并且要运行的JavaFX应用程序线程一些逻辑.
  • Worker当您在JavaFX应用程序线程上运行时,请使用a 并希望在新线程上生成某些逻辑或(特别是)I/O,以便不阻止JavaFX应用程序线程.

你绝不会希望做一个内部网络I/O Platform.runLaterrun方法,但常常会想这样做的Workercall方法.

任务和服务

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

利用javadoc TaskServicejavadoc示例中的设计模式,简化线程安全应用程序的创建,其功能包括:

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

一起使用Workers和Platform.runLater

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

使用现有的线程系统

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

小心编写多线程代码

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

回答你的一些补充问题

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

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

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

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

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

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

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

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

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

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