【问题标题】:java - execute each SwingWorker class one after anotherjava - 一个接一个地执行每个 SwingWorker 类
【发布时间】:2012-05-10 08:15:00
【问题描述】:

我有多个扩展 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<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {
        //do something

        return null;
    }

}

public class ClassSwingW2 extends SwingWorker<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {
        //do something

        return null;
    }

}

public class ClassSwingW3 extends SwingWorker<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {
        //do something

        return null;
    }

}

我希望 csw2 在 csw1 完成后执行,而 csw3 在 csw2 完成后执行。我不想要他们 同时执行。我将如何做到这一点?谢谢

【问题讨论】:

  • 是否必须使用 SwingWorker 的子类?这是相关的。

标签: java multithreading swing swingworker


【解决方案1】:

您可以使用get() method 而不是execute() - 它会阻塞直到 SwingWorker 完成其工作。只要确保您没有从 EDT 调用它即可。

Javadoc 提取:

如有必要,等待计算完成,然后检索其结果。 注意:在 Event Dispatch Thread 上调用 get 会阻止所有事件(包括重绘)被处理,直到此 SwingWorker 完成。

【解决方案2】:
  • 我建议通过监听 PropertyChangeListener 来查看 Executor 调用 SwingWorker 实例

  • read carrefully this thread,特别是@trashgod的回答

Executor & SwingWorker & PropertyChangeListener & Swing 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<Void, Integer> {

        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<Integer> 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)

【讨论】:

    【解决方案3】:

    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<Integer, Void> worker = new SwingWorker<Integer, Void>() {
          private int sleepDummy = new Random().nextInt(50) + 1;
          private int lengthOfTask = 120;
          @Override protected Integer doInBackground() {
            int current = 0;
            while(current<lengthOfTask && !isCancelled()) {
              current++;
              try {
                Thread.sleep(sleepDummy);
              } catch(InterruptedException ie) {
                break;
              }
              setProgress(100 * current / lengthOfTask);
            }
            return sleepDummy*lengthOfTask;
          }
          @Override protected void done() {
            try {
              System.out.println(get()+"ms");
            } catch(Exception ignore) {
              ignore.printStackTrace();
            }
          }
        };
        worker.addPropertyChangeListener(new ProgressListener(bar));
        executor.execute(worker);
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new SingleThreadExecutorTest().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    }
    class ProgressListener implements PropertyChangeListener {
      private final JProgressBar progressBar;
      ProgressListener(JProgressBar progressBar) {
        this.progressBar = progressBar;
        this.progressBar.setValue(0);
      }
      @Override public void propertyChange(PropertyChangeEvent evt) {
        String strPropertyName = evt.getPropertyName();
        if("progress".equals(strPropertyName)) {
          progressBar.setIndeterminate(false);
          int progress = (Integer)evt.getNewValue();
          progressBar.setValue(progress);
        }
      }
    }
    

    【讨论】:

      【解决方案4】:

      Memory Consistency Properties 总结了 JLS:“线程中的每个动作发生在之前该线程中的每个动作都在程序顺序的后面。”只需将每个工作人员的doInBackground() 重新分解为一个单独的方法,然后依次调用每个方法:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多