JAVA - 为什么 SwingWorker 线程不处理所有发布的字符串?
JAVA - Why SwingWorker Thread not processing all publish strings?
我正在使用一个 Worker class,它扩展 SwingWorker
并在它的 process
方法中处理 String 值,并将它们打印到 JTextArea。
所以我进行了很多 publish(some_string)
调用以将字符串打印到文本区域,但是当我执行我的工作线程时 - 它不打印我在 doInBackground()
方法中发布的所有文本。它错过了很多发布电话,我只得到了我想要的部分单词。
但是当我执行线程并放置一个断点并且一步步跟随它 我可以看到它确实打印了发布调用中的 所有字符串。
做该做的事。
为什么在debug模式下能正常运行,在正常模式下却不行?
我的代码:
public class Worker extends SwingWorker<Void , String>
{
public Worker(int int optionOfWork){};
protected Void doInBackground() throws Exception
{
...
publish("Hellow");
publish("This is a test");
...
// a lot of **publish(some_word) calls**
...
publish("Some more words");
}//doInBackground()
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
@override
protected void done()
{
publish("\nDone");
}
}//Worker class
我在主线程中所做的就是创建一个 Worker 对象并执行它:
Worker worker = new Worker();
我使用 worker.excute();
启动它
改变这个:
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
@override
protected void done()
{
publish("\nDone");
}
对此:
@override
protected void process(List<String> wordsToPrint) {
for (String text: wordsToPrint) {
mainWindowTextArea.append(text + "\n");
}
}
@override
protected void done() {
publish("\nDone");
try {
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
for循环一般就是你如何处理传入process方法的String列表。不要忘记在您的 SwingWorker 上调用 get()
如果只是为了检查是否已抛出任何异常。如果仍然卡住,那么是的,创建 post mcve.
您可能需要在 publish(...)
调用之间放置一些 Thread.sleep(10)
以防止调用占用 CPU。
例如:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class SwingWorkerExample extends JPanel {
private JTextArea textArea = new JTextArea(30, 40);
private MyWorker myWorker;
public SwingWorkerExample() {
textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Start Worker") {
@Override
public void actionPerformed(ActionEvent e) {
if (myWorker != null && !myWorker.isDone()) {
myWorker.setLoopRunning(false);
}
myWorker = new MyWorker();
myWorker.execute();
}
}));
bottomPanel.add(new JButton(new AbstractAction("Stop Worker") {
@Override
public void actionPerformed(ActionEvent e) {
if (myWorker != null && !myWorker.isDone()) {
myWorker.setLoopRunning(false);
}
}
}));
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
private class MyWorker extends SwingWorker<Void, String> {
private volatile boolean loopRunning = true;
@Override
protected Void doInBackground() throws Exception {
for (int j = 0; j < 1000 && loopRunning; j++) {
for (int i = 0; i < 1000 && loopRunning; i++) {
String text = String.format("My Text %03d", i);
publish(text);
TimeUnit.MILLISECONDS.sleep(10);
}
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String text : chunks) {
textArea.append(text + "\n");
}
}
@Override
protected void done() {
textArea.append("Done\n");
try {
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public void setLoopRunning(boolean running) {
this.loopRunning = running;
}
public boolean isLoopRunning() {
return loopRunning;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwingWorkerExample mainPanel = new SwingWorkerExample();
JFrame frame = new JFrame("SwingWorkerExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
您仅附加最后发布的字符串(在给定块中)
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
将其更改为
@override
protected void process(List<String> wordsToPrint)
{
for(String part:wordsToPrint){
mainWindowTextArea.append(part);
}
}
当您调用 publish
时,并不意味着 process
会立即被调用。相反,已发布的条目会被堆叠起来,并在某个时间点作为项目列表传递。
我正在使用一个 Worker class,它扩展 SwingWorker
并在它的 process
方法中处理 String 值,并将它们打印到 JTextArea。
所以我进行了很多 publish(some_string)
调用以将字符串打印到文本区域,但是当我执行我的工作线程时 - 它不打印我在 doInBackground()
方法中发布的所有文本。它错过了很多发布电话,我只得到了我想要的部分单词。
但是当我执行线程并放置一个断点并且一步步跟随它 我可以看到它确实打印了发布调用中的 所有字符串。
做该做的事。
为什么在debug模式下能正常运行,在正常模式下却不行?
我的代码:
public class Worker extends SwingWorker<Void , String>
{
public Worker(int int optionOfWork){};
protected Void doInBackground() throws Exception
{
...
publish("Hellow");
publish("This is a test");
...
// a lot of **publish(some_word) calls**
...
publish("Some more words");
}//doInBackground()
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
@override
protected void done()
{
publish("\nDone");
}
}//Worker class
我在主线程中所做的就是创建一个 Worker 对象并执行它:
Worker worker = new Worker();
我使用 worker.excute();
改变这个:
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
@override
protected void done()
{
publish("\nDone");
}
对此:
@override
protected void process(List<String> wordsToPrint) {
for (String text: wordsToPrint) {
mainWindowTextArea.append(text + "\n");
}
}
@override
protected void done() {
publish("\nDone");
try {
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
for循环一般就是你如何处理传入process方法的String列表。不要忘记在您的 SwingWorker 上调用 get()
如果只是为了检查是否已抛出任何异常。如果仍然卡住,那么是的,创建 post mcve.
您可能需要在 publish(...)
调用之间放置一些 Thread.sleep(10)
以防止调用占用 CPU。
例如:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class SwingWorkerExample extends JPanel {
private JTextArea textArea = new JTextArea(30, 40);
private MyWorker myWorker;
public SwingWorkerExample() {
textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Start Worker") {
@Override
public void actionPerformed(ActionEvent e) {
if (myWorker != null && !myWorker.isDone()) {
myWorker.setLoopRunning(false);
}
myWorker = new MyWorker();
myWorker.execute();
}
}));
bottomPanel.add(new JButton(new AbstractAction("Stop Worker") {
@Override
public void actionPerformed(ActionEvent e) {
if (myWorker != null && !myWorker.isDone()) {
myWorker.setLoopRunning(false);
}
}
}));
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
private class MyWorker extends SwingWorker<Void, String> {
private volatile boolean loopRunning = true;
@Override
protected Void doInBackground() throws Exception {
for (int j = 0; j < 1000 && loopRunning; j++) {
for (int i = 0; i < 1000 && loopRunning; i++) {
String text = String.format("My Text %03d", i);
publish(text);
TimeUnit.MILLISECONDS.sleep(10);
}
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String text : chunks) {
textArea.append(text + "\n");
}
}
@Override
protected void done() {
textArea.append("Done\n");
try {
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public void setLoopRunning(boolean running) {
this.loopRunning = running;
}
public boolean isLoopRunning() {
return loopRunning;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwingWorkerExample mainPanel = new SwingWorkerExample();
JFrame frame = new JFrame("SwingWorkerExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
您仅附加最后发布的字符串(在给定块中)
@override
protected void process(List<String> wordsToPrint)
{
String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
mainWindowTextArea.append(lastWord); // not printing\appending all the words sent here by the publish calls
}
将其更改为
@override
protected void process(List<String> wordsToPrint)
{
for(String part:wordsToPrint){
mainWindowTextArea.append(part);
}
}
当您调用 publish
时,并不意味着 process
会立即被调用。相反,已发布的条目会被堆叠起来,并在某个时间点作为项目列表传递。