java – 一个接一个地执行每个SwingWorker类

我有多个类扩展SwingWorker。 我希望实现的是逐个执行每个类(不执行上一个类’done方法中的下一个类)。 例如,假设我有:

ClassSwingW1 csw1 = new ClassSwingW1(); csw1.execute; ClassSwingW2 csw2 = new ClassSwingW2(); csw2.execute; ClassSwingW3 csw3 = new ClassSwingW3(); csw3.execute; 

等等。

 public class ClassSwingW1 extends SwingWorker { @Override protected Void doInBackground() throws Exception { //do something return null; } } public class ClassSwingW2 extends SwingWorker { @Override protected Void doInBackground() throws Exception { //do something return null; } } public class ClassSwingW3 extends SwingWorker { @Override protected Void doInBackground() throws Exception { //do something return null; } } 

我希望csw2在csw1完成后执行,csw3在csw2完成后执行。 我不希望它们同时执行。 我怎么做到这一点? 谢谢

您可以使用get()方法而不是execute() – 它将阻塞,直到SwingWorker完成其工作。 只要确保你没有从EDT调用它。

Javadoc提取物:

如果需要等待计算完成,然后检索其结果。 注意:调用事件调度线程上的get会阻止所有事件(包括重新绘制)被处理,直到此SwingWorker完成。

  • 我建议通过监听PropertyChangeListener来查看Executor调用SwingWorker实例

  • 请仔细阅读这篇post ,特别是@trashgod的回答

ExecutorSwingWorkerPropertyChangeListenerSwing GUI

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import java.util.Random; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.Timer; import javax.swing.border.EmptyBorder; public class ExecutorAndSwingWorker2 { private JFrame frame = new JFrame(); private JButton button1; private JButton button2; private JButton button3; private JButton button4; private JPanel buttonPanel = new JPanel(); private Executor executor = Executors.newCachedThreadPool(); private javax.swing.Timer timer1; private javax.swing.Timer timer2; private javax.swing.Timer timer3; private javax.swing.Timer timer4; private Random random = new Random(); public ExecutorAndSwingWorker2() { button1 = new JButton(" Executor + SwingWorker Thread No.1 "); button1.setFocusable(false); button2 = new JButton(" Executor + SwingWorker Thread No.2 "); button3 = new JButton(" Executor + SwingWorker Thread No.3 "); button4 = new JButton(" Executor + SwingWorker Thread No.4 "); buttonPanel = new JPanel(); buttonPanel.setBorder(new EmptyBorder(15, 15, 15, 15)); buttonPanel.setLayout(new GridLayout(2, 2, 20, 20)); buttonPanel.add(button1); buttonPanel.add(button2); buttonPanel.add(button3); buttonPanel.add(button4); frame.setTitle("Shaking Button Demo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(buttonPanel); frame.setPreferredSize(new Dimension(700, 170)); frame.setLocation(150, 100); frame.pack(); frame.setVisible(true); executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT } private void startButton1() { System.out.println("Starting long Thread == startButton1()"); try { Thread.sleep(15000); } catch (InterruptedException ex) { } } private void startButton2() { System.out.println("Starting long Thread == startButton2()"); try { Thread.sleep(17500); } catch (InterruptedException ex) { } } private void startButton3() { System.out.println("Starting long Thread == startButton3()"); try { Thread.sleep(12500); } catch (InterruptedException ex) { } } private void startButton4() { System.out.println("Starting long Thread == startButton4()"); try { Thread.sleep(20000); } catch (InterruptedException ex) { } } private void colorAction1() { timer1 = new Timer(1000, new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { random = new Random(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { button1.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); button1.validate(); button1.repaint(); } }); } }); timer1.setDelay(500); timer1.setRepeats(true); timer1.start(); } private void colorAction2() { timer2 = new Timer(1200, new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { random = new Random(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { button2.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); button2.validate(); button2.repaint(); } }); } }); timer2.setDelay(500); timer2.setRepeats(true); timer2.start(); } private void colorAction3() { timer3 = new Timer(1400, new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { random = new Random(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { button3.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); button3.validate(); button3.repaint(); } }); } }); timer3.setDelay(500); timer3.setRepeats(true); timer3.start(); } private void colorAction4() { timer4 = new Timer(1600, new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { random = new Random(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { button4.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128))); button4.validate(); button4.repaint(); } }); } }); timer4.setDelay(500); timer4.setRepeats(true); timer4.start(); } private void endButton1() { timer1.stop(); button1.setBackground(null); System.out.println("Long Thread Ends == startButton1()"); executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton3")); // non on EDT } private void endButton2() { timer2.stop(); button2.setBackground(null); System.out.println("Long Thread Ends == startButton2()"); } private void endButton3() { timer3.stop(); button3.setBackground(null); System.out.println("Long Thread Ends == startButton3()"); executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton2")); // non on EDT executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton4")); // non on EDT } private void endButton4() { timer4.stop(); button4.setBackground(null); System.out.println("Long Thread Ends == startButton4()"); executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT } private class MyTask extends SwingWorker { private String str; private String namePr; private JDialog dialog = new JDialog(); MyTask(String str) { this.str = str; addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr)); } @Override protected Void doInBackground() throws Exception { if (str.equals("startButton1")) { colorAction1(); startButton1(); } else if (str.equals("startButton2")) { colorAction2(); startButton2(); } else if (str.equals("startButton3")) { colorAction3(); startButton3(); } else if (str.equals("startButton4")) { colorAction4(); startButton4(); } return null; } @Override protected void process(List progress) { System.out.println(str + " " + progress.get(progress.size() - 1)); } @Override protected void done() { if (str.equals("startButton1")) { endButton1(); } else if (str.equals("startButton2")) { endButton2(); } else if (str.equals("startButton3")) { endButton3(); } else if (str.equals("startButton4")) { endButton4(); } } } private class SwingWorkerCompletionWaiter implements PropertyChangeListener { private JDialog dialog; private String str; private String namePr; SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) { this.dialog = dialog; this.str = str; this.namePr = namePr; } @Override public void propertyChange(PropertyChangeEvent event) { if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) { System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue()); } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) { System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); } else { System.out.println("Thread Status with Name :" + str + ", Something wrong happends "); } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ExecutorAndSwingWorker2 executorAndSwingWorker = new ExecutorAndSwingWorker2(); } }); } } 

使用PropertyChangeListener的输出

 Starting long Thread == startButton1() Thread Status with Name :startButton1, SwingWorker Status is STARTED Long Thread Ends == startButton1() Thread Status with Name :startButton1, SwingWorker Status is DONE Starting long Thread == startButton3() Thread Status with Name :startButton3, SwingWorker Status is STARTED Long Thread Ends == startButton3() Thread Status with Name :startButton3, SwingWorker Status is DONE Starting long Thread == startButton2() Starting long Thread == startButton4() Thread Status with Name :startButton2, SwingWorker Status is STARTED Thread Status with Name :startButton4, SwingWorker Status is STARTED Long Thread Ends == startButton2() Thread Status with Name :startButton2, SwingWorker Status is DONE Long Thread Ends == startButton4() Thread Status with Name :startButton4, SwingWorker Status is DONE Starting long Thread == startButton1() Thread Status with Name :startButton1, SwingWorker Status is STARTED Long Thread Ends == startButton1() Thread Status with Name :startButton1, SwingWorker Status is DONE Starting long Thread == startButton3() Thread Status with Name :startButton3, SwingWorker Status is STARTED Long Thread Ends == startButton3() Starting long Thread == startButton2() Thread Status with Name :startButton3, SwingWorker Status is DONE Starting long Thread == startButton4() Thread Status with Name :startButton2, SwingWorker Status is STARTED Thread Status with Name :startButton4, SwingWorker Status is STARTED Long Thread Ends == startButton2() Thread Status with Name :startButton2, SwingWorker Status is DONE BUILD SUCCESSFUL (total time: 1 minute 34 seconds) 

内存一致性属性总结了JLS:“线程中的每个操作都发生在该线程中的每个操作之前 ,该操作在程序的后面出现。” 只需将每个worker的doInBackground()分解为一个单独的方法,然后按顺序调用每个方法:

 @Override protected Void doInBackground() throws Exception { doCsw1(); doCsw2(); doCsw3(); return null; } 

如何使用Executors.newSingleThreadExecutor()

 import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.*; import java.util.concurrent.*; import javax.swing.*; public class SingleThreadExecutorTest { private Executor executor; private final Box box = Box.createVerticalBox(); public JComponent makeUI() { executor = Executors.newSingleThreadExecutor(); //.newCachedThreadPool(); box.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); JPanel p = new JPanel(new BorderLayout()); p.add(new JButton(new AbstractAction("add") { @Override public void actionPerformed(ActionEvent evt) { doSomethingUseful(); } }), BorderLayout.SOUTH); p.add(new JScrollPane(box)); return p; } private void doSomethingUseful() { JProgressBar bar = new JProgressBar(0, 100); box.add(bar); box.add(Box.createVerticalStrut(8)); box.revalidate(); SwingWorker worker = new SwingWorker() { private int sleepDummy = new Random().nextInt(50) + 1; private int lengthOfTask = 120; @Override protected Integer doInBackground() { int current = 0; while(current