How to share data with two(2) SwingWorker class in Java
Solution 1:
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();
}
});
}
}
Solution 2:
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();
}
}
Solution 3:
PipedReader/Writer for character data & PipedInput/OutputStream for binary data
in java.io.
Regards, Stéphane