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.runLater的run方法,但常常会想这样做的Worker的call方法.
任务和服务
考虑使用Worker的Task或Service子类.这些是FutureTask的 JavaFX包装器(后者又是Runnable).Workers提供了一种调用方法来在后台线程上运行逻辑.它们维护执行状态(使用线程安全回调通知JavaFX线程以进行状态更改)并通过值,消息和异常属性返回调用结果.
利用javadoc Task和Servicejavadoc示例中的设计模式,简化线程安全应用程序的创建,其功能包括:
一起使用Workers和Platform.runLater
此外,使用Task和Service使用不相容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冻结.