Java 从SwingWorker调用done方法时必须使用Runnable.run吗
作为学习SwingWorker的一部分,我在浏览源代码时发现了以下代码。关于这一点,我有一个问题Java 从SwingWorker调用done方法时必须使用Runnable.run吗,java,swing,future,swingworker,Java,Swing,Future,Swingworker,作为学习SwingWorker的一部分,我在浏览源代码时发现了以下代码。关于这一点,我有一个问题 private void doneEDT() { Runnable doDone = new Runnable() { public void run() { done(); } }; if (SwingUtiliti
private void doneEDT() {
Runnable doDone =
new Runnable() {
public void run() {
done();
}
};
if (SwingUtilities.isEventDispatchThread()) {
doDone.run();
} else {
doSubmit.add(doDone);
}
}
上面的doneEDT是从SwingWorker构造函数调用的,如下所示
public SwingWorker() {
Callable<T> callable =
new Callable<T>() {
public T call() throws Exception {
setState(StateValue.STARTED);
return doInBackground();
}
};
future = new FutureTask<T>(callable) {
@Override
protected void done() {
doneEDT();
setState(StateValue.DONE);
}
};
state = StateValue.PENDING;
propertyChangeSupport = new SwingWorkerPropertyChangeSupport(this);
doProcess = null;
doNotifyProgressChange = null;
}
publicswingworker(){
可调用的可调用的=
新的可调用(){
public T call()引发异常{
设置状态(StateValue.STARTED);
返回doInBackground();
}
};
future=新的FutureTask(可调用){
@凌驾
受保护的void done(){
不需要();
设置状态(StateValue.DONE);
}
};
state=StateValue.PENDING;
propertyChangeSupport=新的SwingWorkerPropertyChangeSupport(此);
doProcess=null;
doNotifyProgressChange=null;
}
问题:
为什么done()
方法被包装在doneEDT方法中的Runnable
中?。可以直接调用done()
方法,而无需将其包装在Runnable
right?中?。所以我想把它包装在一个可运行的中有什么好处
所以我想到了这个问题。你把两种不同的done()
方法混为一谈。其中一个来自您打算覆盖的SwingWorker
。在done()
的实现中,不需要对Runnable
进行任何特殊处理,只需要您自己的代码。(一个健壮的done()
实现将检查isCancelled
,如果您没有在其他地方调用它,可能会调用get()
,并处理工作人员可能抛出的任何异常,等等。但您不需要包装一个Runnable
来执行这些操作。)
另一种方法是FutureTask
。这会让人困惑,因为SwingWorker本身使用FutureTask来处理并发性的“真正”工作。FutureTask#done()
也意味着被客户端覆盖,但在这种情况下,客户端是SwingWorker,而不是您
调用execute()时,SwingWorker的future
(FutureTask的私有实例变量)会启动,下面是发生的情况:
future.run()
在工作线程中运行
future.run()
调用如上所述传入的可调用项,将状态更改为STARTED(发送属性事件)并调用doInBackground
。您自己的工作代码运行并返回结果
future.run()
调用自己的“set”方法来存储结果并将计算标记为完成。它还调用一个私有方法finishCompletion
future.finishCompletion()
唤醒调用SwingWorker的get()
(因此一直被阻止)的所有其他线程。对get()
的调用可以在该列表其余部分发生的同时将计算结果返回给调用方
future.finishCompletion()
调用自己的done()
。通常这是一个空方法,但正如您上面引用的,SwingWorker进行了重写。因此,这个特定的FutureTaskdone()
还做了两件事:首先,它调用SwingWorker#doneEDT()
,它只是在事件调度线程上调用SwingWorker#done()
。这是在SwingWorker子类中重写的done()
版本。其次,它将发送另一个属性更改事件的状态更改为DONE
future
的finishCompletion()
返回其“set”方法,该方法返回到执行一些内务处理的run()
,然后返回。在这一点上,worker线程被释放出来用于其他事情(新工作、睡眠、爱好等等)
如果您想对SwingWorker的done()
进行子类化,那么您自己的参与将仅限于SwingWorker的done()。由于SwingWorker所做的杂耍,您自己对done()
的重写可以保证在事件分派线程上运行,因此您可以安全地使用Swing可视组件进行操作。请注意,如果SwingWorker被取消,也会调用done()
,即使在execute()
之前调用了cancel()
——事实上,done()
在cancel()
返回之前调用了done(),因此请检查覆盖内的相应状态。您将两个不同的done()
方法。其中一个来自您打算覆盖的SwingWorker
。在done()
的实现中,不需要对Runnable
进行任何特殊处理,只需要您自己的代码。(一个健壮的done()
实现将检查isCancelled
,如果您没有在其他地方调用它,可能会调用get()
,并处理工作人员可能抛出的任何异常,等等。但您不需要包装一个Runnable
来执行这些操作。)
另一种方法是FutureTask
。这会让人困惑,因为SwingWorker本身使用FutureTask来处理并发性的“真正”工作。FutureTask#done()
也意味着被客户端覆盖,但在这种情况下,客户端是SwingWorker,而不是您
调用execute()时,SwingWorker的future
(FutureTask的私有实例变量)会启动,下面是发生的情况:
future.run()
在工作线程中运行
future.run()
调用如上所述传入的可调用项,将状态更改为STARTED(发送属性事件)并调用doInBackground
。你自己的工人代码r