Java-SwingWorker-问题
我正在开发一个 Java 桌面应用程序。此应用程序执行相同的任务 public class MyTask Implements Callable
同时在多个线程中。
现在,当用户单击“开始”按钮时,我创建了一个 SwingWorker myWorker 并执行了它。
现在,此 myWorker
创建 MyTask
的多个实例,并将它们提交给 ExecutorService
。
每个 MyTask 实例都有一个循环,并在每次迭代时生成中间结果。现在,我想在生成每个 MyTask
实例后立即收集这些中间结果。然后,从每个 MyTask
实例收集这些中间结果后,我想通过 SwingWorker.publish(MyObject)
发布它,以便在 EDT 上显示进度。
Q1.我该如何实现这个?我是否应该创建 SwingWorker
的 MyTask
子类而不是 Callable
来获得中间结果,因为我认为 Callable
仅返回最终结果。
Q2。如果回答Q1。是的,那么您能给我一个小例子来展示如何获取这些中间结果并聚合它们,然后从主 SwingWorker
发布它们吗?
Q3.如果在这种情况下我无法使用SwingWorker
,那么我该如何实现呢?
I am developing a Java Desktop Application. This app executes the same task public class MyTask implements Callable<MyObject> {
in multiple thread simultaneously.
Now, when a user clicks on a "start" button, I have created a SwingWorker myWorker
and have executed it.
Now, this myWorker
creates multiple instances of MyTask
and submits them to an ExecutorService
.
Each MyTask
instance has a loop and generates an intermediate result at every iteration. Now, I want to collect these intermediate results from each MyTask
instances as soon as they are generated. Then after collecting these intermediate results from every MyTask
instance, I want to publish it through SwingWorker.publish(MyObject)
so that the progress is shown on the EDT.
Q1. How can I implement this? Should I make MyTask
subclass of SwingWorker
instead of Callable
to get intermediate results also, because I think that Callable
only returns final result.
Q2. If the answer of Q1. is yes, then can you give me a small example to show how can I get those intermediate results and aggregate them and then publish them from main SwingWorker
?
Q3. If I can't use SwingWorker
in this situation, then how can I implement this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看一下 ExecutorCompletionService。它是一个 Executor,提供
take
方法来检索任何已完成任务的结果。更新:
扩展
SwingWorker
不会执行您想要的操作,因为它专门用于将工作从 EDT 卸载到后台线程。您不能使用它将工作从后台线程卸载到其他后台线程。调用SwingWorker.publish
会产生相当于SwingUtilities.invokeLater
的结果。据我所知,没有任何机制可以从后台线程到后台线程执行相同的操作。最好的选择是使用对Queue
的引用来创建MyTask
,并让SwingWorker.doInBackground
轮询队列以获取中间结果。Take a look at ExecutorCompletionService<T>. It's an Executor that supplies a
take
method to retrieve the result of any completed task.Update:
Extending
SwingWorker
will not do what you want as it is specifically intended for offloading work from the EDT to a background thread. You can't use it to offload work from a background thread to other background threads. Calls toSwingWorker.publish
result in the equivalent of aSwingUtilities.invokeLater
. There is no mechanism I am aware of for doing the same thing from a background thread to a background thread. Your best bet is to create yourMyTask
with a reference to aQueue
and have yourSwingWorker.doInBackground
poll the queue for intermediate results.A1+A2。
Yatendra,您的 Main
SwingWorker
是否必须是唯一将临时结果传递给EDT
的?如果您的任务也是SwingWorker
实例,则 Main Worker 可以将将临时结果发送回EDT
的责任委托给它们,而只需处理TaskWorkers< /code> 生命周期。
请记住,这只是一个测试,我知道有一些丑陋的 Thread.sleep(long) 调用。
A3
但是,如果您的项目需要另一个 ExecutorService 来安排任务执行,那么我将实现类似的发布进程机制来执行主 Swing 工作线程和该任务线程之间的通信。虽然看起来很重复,但您可以使用 java.concurrent.ConcurrentQueue 来存储可用的临时结果吗?
PS:我几天前才注意到,但是 SwingWorkers 周围有一个恼人的错误,阻止其 ExecutorService 缓存未使用的线程。
A1+A2.
Yatendra, is it necessary that your Main
SwingWorker
must be the only one that passes interim results to theEDT
? If your tasks were alsoSwingWorker
instances, the Main Worker could delegate the responsability of sending interim results back to theEDT
to them and just take care of theTaskWorkers
life-cycle.Keep mind that this is just a test, I know that there are a few ugly
Thread.sleep(long)
calls.A3
But if having another
ExecutorService
to schedule your task execution is a requirement in your project, I would implement a similar publish-process mechanism to perform communication between your Main Swing Worker Thread and that Task Thread. Although it seems to be repetitive, You may use ajava.concurrent.ConcurrentQueue
to store interim results as they become available?PS: I just noticed a few days ago, but there is an annoying bug around SwingWorkers that prevents its ExecutorService from caching unused threads.
SwingWorker 也是未来。因此,它具有 get() 方法,可以在 did() 方法内部使用该方法,以在该方法完成时获取 doInBackground() 的结果。
因此,结构变得有点像:
A SwingWorker is also a Future. As such it has the get() method which can be used inside the done() method to get the result of doInBackground() when that method finishes.
Thus the construct becomes somewhat like: