Java-SwingWorker-我们可以从另一个SwingWorker中调用一个SwingWorker而不是EDT吗
我有一个Java-SwingWorker-我们可以从另一个SwingWorker中调用一个SwingWorker而不是EDT吗,java,user-interface,swingworker,Java,User Interface,Swingworker,我有一个SwingWorker,如下所示: public class MainWorker extends SwingWorker(Void, MyObject) { : : } 我从EDT调用了上述Swing Worker: MainWorker mainWorker = new MainWorker(); mainWorker.execute(); 现在,mainWorker创建了一个MyTask类的10个实例,这样每个实例都将在自己的线程上运行,以便更快地完成工作 但问
SwingWorker
,如下所示:
public class MainWorker extends SwingWorker(Void, MyObject) {
:
:
}
我从EDT调用了上述Swing Worker
:
MainWorker mainWorker = new MainWorker();
mainWorker.execute();
现在,mainWorker
创建了一个MyTask
类的10个实例,这样每个实例都将在自己的线程上运行,以便更快地完成工作
但问题是我想在任务运行时不时更新gui。我知道如果任务是由mainWorker
本身执行的,我可以使用publish()
和process()
方法来更新gui
但是,由于任务是由不同于
Swingworker
线程的线程执行的,我如何从执行任务的线程生成的中间结果更新gui。即使不使用Swingworker,也可以始终使用SwingUtilities.invokeLater(…)或SwingUtilities.invokeAndWait(…)在EDT中发布要执行的事情
编辑:假设您有一个线程执行某些代码,您可以始终与EDT交互,如下面的示例所示
public void aMethodExecutedInAThread() {
// Do some computation, calculation in a separated Thread
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Post information in the EDT
// This code is executed inside EDT
}
});
}
阅读这些小贴士可以清楚地了解你的问题
SwingWorker的API文档提供了以下提示: 调用doInBackground()方法 在这条线上。这是所有人 应开展背景活动。 通知PropertyChangeListeners的步骤 关于绑定属性更改使用 火性能变化和 getPropertyChangeSupport()方法。通过 默认情况下,有两个绑定属性 可用:状态和进度
MainWorker
可以实现PropertyChangeListener
。然后,它可以使用其属性ChangeSupport
注册自身:
getPropertyChangeSupport().addPropertyChangeListener( this );
MainWorker
可以将其PropertyChangeSupport
对象提供给它创建的每个MyTask
对象
new MyTask( ..., this.getPropertyChangeSupport() );
然后,MyTask
对象可以使用PropertyChangeSupport.firePropertyChange
方法将进度或属性更新通知其MainWorker
MainWorker
收到通知后,可以使用SwingUtilities.invokeLater
或SwingUtilities.invokeAndWait
通过EDT更新Swing组件
protected Void doInBackground() {
final int TASK_COUNT = 10;
getPropertyChangeSupport().addPropertyChangeListener(this);
CountDownLatch latch = new CountDownLatch( TASK_COUNT ); // java.util.concurrent
Collection<Thread> threads = new HashSet<Thread>();
for (int i = 0; i < TASK_COUNT; i++) {
MyTask task = new MyTask( ..., latch, this.getPropertyChangeSupport() ) );
threads.add( new Thread( task ) );
}
for (Thread thread: threads) {
thread.start();
}
latch.await();
return null;
}
protectedvoid doInBackground()受保护{
最终整数任务计数=10;
getPropertyChangeSupport().addPropertyChangeListener(此);
CountDownLatch latch=新的CountDownLatch(任务计数);//java.util.concurrent
集合线程=新HashSet();
对于(int i=0;i
下面是一个使用来启动多个线程的。确保仅当所有线程都已完成时返回。每个线程都使用线程安全的方法来更新GUI,但这是一个方便的替代方法。@Matthieu-您可以用一个示例来详细说明或提供一些链接吗?@Yatendra Goel:请将Continuations视为对象。注意这里的内存一致性影响,EDT可能看不到由ametodexecutedAthread()所做的更改,除非EDT在包含更改的对象上进行同步(或者修改的属性标记为volatile)。@Justin:什么意思?SwingUtilities工作得很好,并且已经有一段时间了。操作(内存写入)由AmethodExecutedAthrad()拍摄需要一个与匿名runnable(在EDT中运行)的before before关系。从EventQueue
(或SwingUtilities
)实际上不清楚invokeLater()
和EDT是否获得相同的锁(通过它们可能在内部执行)上述所有文章中提到的SwingWorker
已经过时。自java 1.6以来,它一直是jdk的一部分,与之前的SwingWorker
@Yatendra Goel不一样:java 5有一个源代码兼容的后端口。为什么EventQueue.invokeLater()
而不是SwingUtilities.invokeLater()
?“从1.3开始,这个方法只是java.awt.EventQueue.invokeLater()的一个掩护。”+1表示CountDownLatch
,我以前在您的回答中忽略了这一点。使用latch.wait()
可以确保子线程所做的更改在doInBackground()的末尾可见
。假设任务是独立的,您如何通过firePropertyChange传达更新来自哪个任务?例如,假设每个任务更新完成百分比,后台线程如何计算所有任务的总完成百分比?@mdma执行该计算的信息可由PropertyChangeEvent发射器提供;e、 例如,作为表示元组的bean(任务名称、完成百分比、总工作百分比).firePropertyChange将java.lang.Object作为属性值。嗨,Noel,我正在考虑实现类似的解决方案。我想知道,8年后,上述代码是否仍然是最佳解决方案,或者您是否会对其进行任何更改?您希望将哪种结果发布到GUI?它们是特定于子任务的结果吗(例如,每个子任务正在做什么),或聚合所有任务的结果(例如,所有任务的完成百分比)。我想将对象发布到GUI,该GUI将用于填充JTable
。