您应该查看Worker Threads and SwingWorker 和JavaDocs for SwingWorker,这将为您提供更多信息。
基本上,publish 将值放入队列中,该队列将在 EDT 上下文中传递给 publish 方法。这用于允许将信息从工作人员的后台线程传递到 EDT,在 EDT 中可以使用这些值安全地更新 UI。
应该使用done 方法来获取后台操作的结果(假设它有一个),可以使用get 方法检索该结果,该方法将返回从doInBackground 方法返回的值或者生成的异常
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
public class Test {
public static void main(String[] args) throws InterruptedException {
ExampleWorker worker = new ExampleWorker();
worker.execute();
Thread.sleep(100);
try {
System.out.println(">> " + worker.get());
} catch (ExecutionException ex) {
ex.printStackTrace();
}
}
public static class ExampleWorker extends SwingWorker<String, Integer> {
private int n = 0;
private long startTime;
@Override
protected String doInBackground() throws Exception {
System.out.println("doInBackground()");
startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < 3000) {
publish(n++);
Thread.yield();
}
return "What is this used for?";
}
@Override
protected void process(List<Integer> chunks) {
for (int value : chunks) {
System.out.println(value);
}
}
@Override
protected void done() {
System.out.println("Done: " + n);
}
}
}
更新了一个更有针对性的例子...
我没有处理方法,因为我不想在后台操作完成之前将信息传递给 EDT。
那么不要使用publish/process,使用done并返回你想要从doInBackground检索的值
我仍然在我的代码中发布的唯一原因是,如果我不取消该过程,没有它就无法工作。
对我来说似乎工作正常,SwingWorker 已经拥有取消状态
get() 不会阻止 EDT 上的所有内容吗?我不希望这样,因为它会阻止我的 GUI 工作
是的,当 worker 运行时,如果 worker 完成,它将立即返回。在您的示例中,由于没有任何 UI 来阻止 JVM 退出,这是一种阻止 JVM 退出的方法
这意味着您可以使用通常在doInBackground 返回后和/或在PropertyChangeListener 内调用的done,具体取决于您的需要
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) throws InterruptedException {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JLabel("Waiting"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
ExampleWorker worker = new ExampleWorker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
ExampleWorker worker = (ExampleWorker) evt.getSource();
switch (worker.getState()) {
case DONE: {
try {
System.out.println("PropertyChange: " + worker.get());
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
frame.dispose();
}
break;
}
}
}
});
worker.execute();
}
});
}
public static class ExampleWorker extends SwingWorker<Integer, Integer> {
private int n = 0;
private long startTime;
@Override
protected Integer doInBackground() throws Exception {
System.out.println("doInBackground()");
startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < 3000) {
n++;
Thread.yield();
}
return n;
}
@Override
protected void process(List<Integer> chunks) {
for (int value : chunks) {
System.out.println(value);
}
}
@Override
protected void done() {
try {
System.out.println("Done: " + get());
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
}
}