简体   繁体   English

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

[英]Javafx: Difference between javafx.concurent and Platform.runLater?

I'm curious as to what exactly the difference is between javafx.concurent and Platform.runLater for multithreaded JavaFx programming. 对于多线程JavaFx编程的javafx.concurent和Platform.runLater之间到底有什么区别,我很好奇。

Does it mean that with javafx.concurrent, we can have multiple actual drawing threads or does it all end up on one thread anyway? 这是否意味着使用javafx.concurrent,我们可以有多个实际的绘图线程,还是全部都结束在一个线程上?

Eg One thing I enjoyed was using JavafX and swing concurrently as they both used 2 different drawing threads. 例如,我喜欢的一件事是使用JavafX并同时摆动,因为它们都使用了2个不同的绘图线程。 I would use swing for the heavy stuff (eg opening a FileChooser) and use JavaFX for the core visual stuff eg playing a seamless, looping video. 我会为较重的内容使用swing(例如,打开FileChooser),而对核心视觉内容使用JavaFX(例如,播放无缝的循环视频)。 However, the mac makes this impossible because of that headless exception error so everything fell on javafx and that meant a lot of pauses when doing things like opening filechoosers. 但是,由于该无头异常错误,mac使其无法实现,因此一切都落在javafx上,这意味着在执行诸如打开文件选择器之类的操作时会出现很多暂停。

If I rewrite my app With javafx.concurrent, could I essentially mimic that 2 draw thread experience as I once did with Swing + JavaFX? 如果我使用javafx.concurrent重写我的应用程序,我是否可以像以前使用Swing + JavaFX一样模仿2个绘制线程的经验?

Platform.runLater Platform.runLater

A Worker is complementary to Platform.runLater . WorkerPlatform.runLater补充。

  • Use Platform.runLater when you are executing off of the JavaFX Application Thread and you want to run some logic on the JavaFX application Thread. 当您从JavaFX应用程序线程中执行时,并且要在JavaFX应用程序线程上运行一些逻辑时,请使用Platform.runLater
  • Use a Worker when you are running on the JavaFX Application Thread and want to spawn some logic or (especially) I/O on a new thread so that you don't block the JavaFX Application Thread. 当您在JavaFX Application Thread上运行并且想要在新线程上生成一些逻辑或(特别是)I / O时,请使用Worker ,以便不阻塞JavaFX Application Thread。

You would never want to do network I/O inside a Platform.runLater 's run method, but would often want to do it in a Worker 's call method. 您永远不会希望在Platform.runLaterrun方法中执行网络I / O,但通常希望在Workercall方法中进行网络I / O。

Task and Service 任务与服务

Consider using the Task or Service subclasses of Worker . 考虑使用WorkerTaskService子类。 These are JavaFX wrappers for FutureTask (which is in turn a Runnable ). 这些是FutureTask的 JavaFX包装器(后者又是Runnable )。 Workers provide a call method to run logic on a background thread. 工作者提供了一种在后台线程上运行逻辑的调用方法。 They maintain execution status (with thread safe callback notification to the JavaFX thread for state changes) and return results of the call via value , message and exception properties. 它们维护执行状态 (通过向JavaFX线程提供线程安全的回调通知来更改状态),并通过valuemessageexception属性返回调用结果。

Take advantage of the design patterns in the Task and Service javadoc examples to simplify creation of thread-safe applications with features such as: 利用Task and Service javadoc示例中的设计模式来简化具有以下功能的线程安全应用程序的创建:

  • Asynchronous fetching of data for UI update. 异步获取数据以更新UI。
  • Periodic message updates for task progress. 定期更新消息以了解任务进度。
  • Constructing Node graphs which are not yet attached to a displayed scene. 构造尚未附加到显示场景的节点图。
  • Monitoring progress via progress bars, etc. 通过进度条等监视进度

Using Workers and Platform.runLater together 一起使用Workers和Platform.runLater

Also, usage of Task and Service is not incompatible with use of Platform.runLater . 另外,使用TaskService与使用Platform.runLater不兼容。 For instance, if you have a very long running Task from which you want to return partial results to the UI periodically or as a buffer fills, then executing Platform.runLater in the task's call method is the way to do that. 例如,如果您有一个运行时间非常长的Task ,您希望从中定期将部分结果返回到UI或在缓冲区填充时返回,则可以在任务的call方法中执行Platform.runLater

Working with existing threading systems 使用现有的线程系统

Workers are useful when you don't have an existing threaded service provided by a library, but are instead creating your own threads to execute in the background. 当您没有库提供的现有线程服务,而是创建自己的线程以在后台执行时,工作器将非常有用。 If you have an existing threaded service, then you will need to use Platform.runLater to perform logic on the JavaFX application thread. 如果您具有现有的线程服务,则需要使用Platform.runLater在JavaFX应用程序线程上执行逻辑。

Be careful writing multi-threaded code 小心编写多线程代码

Note that you still need to know what you are doing, even if you use a Worker . 请注意,即使您使用Worker ,您仍然需要知道您在做什么。 You must still take care that you don't violate standard JavaFX concurrency rules, such as never updating Nodes on the active scene graph (including not updating values that Nodes in the active scene graph are bound to - such as the observable list of items backing a ListView ). 您仍然必须注意不要违反标准JavaFX并发规则,例如从不更新活动场景图中的节点(包括不更新活动场景图中的节点绑定到的值),例如可观察到的项目支持列表ListView )。

Answering some of your addition questions 回答您的一些其他问题

Does it mean that with javafx.concurrent, we can have multiple actual drawing threads or does it all end up on one thread anyway? 这是否意味着使用javafx.concurrent,我们可以有多个实际的绘图线程,还是全部都结束在一个线程上?

There is only one render thread in JavaFX. JavaFX中只有一个渲染线程。 You cannot make more render threads using JavaFX concurrent. 您不能使用JavaFX并发创建更多渲染线程。 You can do things like create nodes off the JavaFX thread or set pixels to an off screen WriteableImage or Canvas using many threads, but eventually every render operation passes through a single thread managed by the JavaFX system over which you have no control. 您可以执行一些操作,例如在JavaFX线程之外创建节点,或者使用许多线程将像素设置为屏幕外的WriteableImage或Canvas,但是最终每个渲染操作都将通过JavaFX系统管理的单个线程,您无法对其进行控制。

If I rewrite my app With javafx.concurrent, could I essentially mimic that 2 draw thread experience as I once did with Swing + JavaFX? 如果我使用javafx.concurrent重写我的应用程序,我是否可以像以前使用Swing + JavaFX一样模仿2个绘制线程的经验?

No. Even if you could, I don't think it would be advisable. 不。即使您可以,我也不建议这样做。 With such a model it is far too easy to create subtle, hard to debug thread processing related errors. 使用这样的模型,创建微妙的,难以调试的线程处理相关错误太容易了。 And the gain you might see from such a setup may be less than you may wish for or expect. 这样设置带来的收益可能会比您期望或期望的要少。

See related articles on why having 2 or more "draw threads" is likely inadvisable: 有关为什么不建议使用2个或更多“绘制线程”的信息,请参阅相关文章:

Java 8 is adding an experimental command line switch to use the same thread for the JavaFX application thread and the Swing event dispatch thread. Java 8添加了一个实验性的命令行开关,以将相同的线程用于JavaFX应用程序线程和Swing事件分配线程。 The main reason for this is that it simplifies the programming model. 这样做的主要原因是它简化了编程模型。

everything fell on javafx and that meant a lot of pauses when doing things like opening filechoosers. 一切都落在javafx上,这意味着在执行诸如打开文件选择器之类的操作时会出现很多暂停。

Perhaps there were inefficiencies in your code (such as performing I/O on the UI thread) which caused the pauses. 也许您的代码效率低下(例如,在UI线程上执行I / O)导致了暂停。

the heavy stuff (eg opening a FileChooser) 繁重的工作(例如,打开FileChooser)

Opening and rendering a FileChooser is not heavy. 打开和呈现FileChooser并不繁琐。 JavaFX can easily handle such an operation without a performance degradation. JavaFX可以轻松处理此类操作,而不会降低性能。 What can be time consuming is stuff related to I/O, for example walking a large file tree recursively to get file attributes. 与I / O相关的工作可能很耗时,例如,递归地遍历大文件树以获取文件属性。 What you can do in such cases is spawn a thread for the I/O run it in a Worker and periodically feed back partial results to the UI thread via Platform.runLater . 在这种情况下,您可以做的是生成一个I / O线程,以便在Worker运行它,并通过Platform.runLater定期将部分结果反馈给UI线程。 Such a scheme will work well. 这样的方案将很好地工作。 The bottleneck is not the drawing, so having another drawing thread provides no advantage. 瓶颈不是图形,因此拥有另一个图形线程不会带来任何好处。 The bottleneck is the slow I/O system and this bottleneck is mitagated by the using a separate thread for I/O so that the main UI thread is not impacted and the user does not experience UI freezes while I/O is occurring. 瓶颈是速度较慢的I / O系统,并且通过为I / O使用单独的线程来掩盖此瓶颈,从而不会影响主UI线程,并且在发生I / O时用户不会遇到UI冻结的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM