我正在尝试在后台运行一个进程三秒钟,并让它可以取消。现在我有一个例子,增加一个int,直到三秒钟或工人被取消。
import java.util.List;
import javax.swing.SwingWorker;
public class Example {
public static void main(String[] args) throws InterruptedException {
ExampleWorker worker = new ExampleWorker();
worker.execute();
Thread.sleep(10);
//worker.cancel(false);
}
}
class ExampleWorker extends SwingWorker<String, Integer> {
private int n = 0;
private long startTime;
private boolean cancelled = false;
@Override
protected String doInBackground() throws Exception {
System.out.println("doInBackground()");
startTime = System.currentTimeMillis();
while (!cancelled && System.currentTimeMillis() - startTime < 3000) {
publish(n++);
}
return "What is this used for?";
}
@Override
protected void done() {
cancelled = true;
System.out.println(n);
}
}
我曾经有一个打印出来的流程方法。我删除了它,但我保留了publish(n++)
。一切正常。但是当我用publish(n++)
替换n++
时,如果我不取消工作人员,则不会打印出任何内容。为什么删除发布会产生此问题?
答案 0 :(得分:1)
您应该查看Worker Threads and SwingWorker和JavaDocs for SwingWorker
,它们会为您提供更多信息。
基本上,publish
将值放在队列中,该队列将在EDT的上下文中传递给publish
方法。这用于允许信息从worker的后台线程传递到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
已经拥有取消状态
并且没有()阻止EDT上的所有内容?我不希望这样,因为它阻止我的GUI工作
是的,当工人正在跑步时,如果工人已经完成,它将立即返回。在您的示例中,由于缺少任何UI以防止JVM退出,这是一种阻止JVM退出的方法
这意味着您可以使用done
通常在doInBackground
返回后和/或PropertyChangeListener
内调用的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();
}
}
}
}
,具体取决于您的需求
DelegateProxyType