Java 从SwingWorker调用done方法时必须使用Runnable.run吗

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

作为学习SwingWorker的一部分,我在浏览源代码时发现了以下代码。关于这一点,我有一个问题

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进行了重写。因此,这个特定的FutureTask
    done()
    还做了两件事:首先,它调用
    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