gpt4 book ai didi

java - 为什么 SwingWorkers 需要发布?

转载 作者:行者123 更新时间:2023-12-01 10:20:54 27 4
gpt4 key购买 nike

我正在尝试在后台运行一个进程三秒钟,并使其可以取消。现在我有一个示例,它递增 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);
}

}

我曾经有一个打印出n的处理方法。我删除了它,但保留了 publish(n++)。一切顺利。但是,当我将 publish(n++) 替换为 n++ 时,如果我不取消工作人员,则不会打印任何内容。为什么删除发布会产生此问题?

最佳答案

您应该看看Worker Threads and SwingWorkerJavaDocs for SwingWorker这将为您提供更多信息。

基本上,publish 将值放入队列中,该队列将被传递到 EDT 上下文中的 publish 方法。这用于允许信息从工作线程的后台线程传递到 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);
}

}

}

更新了更直接的示例...

I don't have a process method because I don't want to pass information to the EDT until the background operation finishes.

然后不要使用publish/process,使用done并返回您想要从doInBackground<检索的值

The only reason I still have publish in my code is because it doesn't work without it, if I don't cancel the process.

似乎对我来说工作正常,并且 SwingWorker 已经拥有取消状态

And doesn't get() block everything on the EDT? I don't want that because it prevents my GUI from working

是的,当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();
}
}

}

}

关于java - 为什么 SwingWorkers 需要发布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35636483/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com