Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share data with two(2) SwingWorker class in Java

I have two SwingWorker class: FileLineCounterThread and FileDivisionThread

I will execute the two threads. When the lines counting thread finishes, it will pass the result to File Division thread.

I do not have an idea on how to pass the result to started thread.

like image 235
eros Avatar asked May 30 '11 00:05

eros


2 Answers

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();
            }
        });
    }
}
like image 79
mKorbel Avatar answered Nov 03 '22 03:11

mKorbel


SwingWorker.execute() is buggy and will only execute tasks serially. Use ExecutorService.execute() for concurrency:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RunnableFuture;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;

public class MyFrame extends JFrame implements ActionListener {

    /**
     * Test Driver
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyFrame frame = new MyFrame("Swing Concurrency Test");
                frame.setVisible(true);
            }
        });
    }

    /**
     * Thread Executor
     * (must be explicitly shutdown, see WindowAdapter below)
     */
    private final ExecutorService exec = Executors.newFixedThreadPool(2);

    /**
     * Button action
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        button.setEnabled(false);
        textArea.append("\nStarting both tasks...\n");

        // start both tasks, pass a reference to outer task
        FileLineCounterThread counterTask = new FileLineCounterThread();
        exec.execute(counterTask);
        FileDivisionThread divisionTask = new FileDivisionThread(counterTask);
        exec.execute(divisionTask);
    }

    /**
     * Counter task
     */
    private class FileLineCounterThread extends SwingWorker<Long, String> {
        private String template = "[FileLineCounterThread] %s\n";

        @Override
        protected Long doInBackground() throws Exception {
            // do some work
            publish("started...");
            Thread.sleep(10000);

            // return the result
            return 42L;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String chunk : chunks) {
                textArea.append(String.format(template, chunk));
            }
        }

        @Override
        protected void done() {
            try {
                textArea.append(String.format(
                        template, "complete.  Counted: " + get()));
            }
            catch (Exception e) {
                // catch any exceptions thrown during execution
                e.printStackTrace();
            }
        }
    }

    /**
     * File Division task 
     */
    private class FileDivisionThread extends SwingWorker<String, String> {
        private RunnableFuture<Long> counterTask;
        private String template = "    [FileDivisionThread] %s\n";

        public FileDivisionThread(RunnableFuture<Long> counterTask) {
            this.counterTask = counterTask;
        }

        @Override
        protected String doInBackground() throws Exception {
            // do some initial work
            publish("started...");
            Thread.sleep(2000);

            // wait for other task to complete and get result
            publish("Waiting for line counter to finish...");
            long numLines = counterTask.get(); 
            publish("Line count received: " + numLines);

            // do the rest of the work and return result
            Thread.sleep(5000);
            return "complete.";
        }

        @Override
        protected void process(List<String> chunks) {
            for (String chunk : chunks) {
                textArea.append(String.format(template, chunk));
            }
        }

        @Override
        protected void done() {
            try {
                textArea.append(String.format(template, get()));
                button.setEnabled(true);
            }
            catch (Exception e) {
                // catch any exceptions thrown during execution
                e.printStackTrace();
            }
        }
    }

    /////////////////////////
    //// GUI Boilerplate ////
    /////////////////////////

    private JScrollPane scroller = new JScrollPane();
    private JTextArea textArea = new JTextArea();
    private JButton button = new JButton("Start");

    public MyFrame(String windowTitle) {
        super(windowTitle);
        initComponents();
    }

    private void initComponents() {
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                exec.shutdownNow();
                System.exit(0);
            }
        });
        button = new JButton("Start");
        button.addActionListener(this);
        textArea = new JTextArea();
        textArea.setColumns(35);
        textArea.setRows(15);
        scroller.setViewportView(textArea);

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new GridBagLayout());

        GridBagConstraints gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new Insets(10, 0, 0, 0);
        getContentPane().add(button, gridBagConstraints);

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new Insets(10, 10, 10, 10);
        getContentPane().add(scroller, gridBagConstraints);

        pack();
    }
}
like image 2
Joe Coder Avatar answered Nov 03 '22 03:11

Joe Coder