10 Replies Latest reply: Jul 13, 2010 5:33 AM by 791266 RSS

    Multiple SwingWorker instances  - Progress Monitor

    843807
      I am working on a Swing app where we are making time consuming Server side calls. I am trying to use Swing Worker so that the GUI will not be frozen.

      My requirement is when the Call to the server is made I need to create an instance of SwingWorker and show a Progress Monitor with an option to cancel on Top of the current calling Frame.

      While the Server call is being made, other UI functions like Menu etc has to be available for the user.

      When the user opens another screen/window I need to create another instance of Swingworker and open another Progress Monitor.

      Basically if I am opening two windows, there will be two Progress monitors on two windows and the user should be able to open another screen/window as well while these 2 are processing.

      When I tried to do something similar, what I noticed is, the doInBackground of the SwingWorker is getting executed synchronosly.

      The second Swing worker instance's doInBackground() doesn't get executed until the first one does. Is this how its supposed to work?
        • 1. Re: Multiple SwingWorker instances  - Progress Monitor
          843807
          Sounds like you're bitten by this bug:

          [SwingWorker deadlocks due one thread in the swingworker-pool|http://bugs.sun.com/view_bug.do?bug_id=6880336]
          • 2. Re: Multiple SwingWorker instances  - Progress Monitor
            843807
            package components;
            
            import java.awt.*;
            import java.awt.event.*;
            
            import javax.swing.*;
            import java.beans.*;
            import java.util.Random;
            
            public class ProgressMonitorTest extends JPanel
                                             implements ActionListener,
                                                        PropertyChangeListener {
            
                private JButton startButton;
                private JButton newButton;
                private JTextArea taskOutput;
                private TestSwingWorker task;
            
                public ProgressMonitorTest() {
                    super(new BorderLayout());
            
                    //Create the demo's UI.
                    startButton = new JButton("Start");
                    startButton.setActionCommand("start");
                    startButton.addActionListener(this);
            
                    
                    newButton = new JButton("New Window");
                    newButton.setActionCommand("start");
                    newButton.addActionListener(new ActionListener() {
                           public void actionPerformed(ActionEvent event) {
                                new ProgressMonitorTest2();
                           }
                     });
                    
                    
                    taskOutput = new JTextArea(5, 20);
                    taskOutput.setMargin(new Insets(5,5,5,5));
                    taskOutput.setEditable(false);
            
                    add(startButton, BorderLayout.PAGE_START);
                    add(newButton, BorderLayout.PAGE_END);
                    add(new JScrollPane(taskOutput), BorderLayout.CENTER);
                    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
            
                }
            
            
             public void actionPerformed(ActionEvent evt) {
                    task = new TestSwingWorker();
                    task.addPropertyChangeListener(this);
                    task.start(ProgressMonitorTest.this);
                    startButton.setEnabled(false);
                }
            
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("progress" == evt.getPropertyName() ) {
                        int progress = (Integer) evt.getNewValue();
                        String message =
                            String.format("Completed %d%%.\n", progress);
                        taskOutput.append(message);
                        if (task.isDone()) {
                            Toolkit.getDefaultToolkit().beep();
                            taskOutput.append("Task completed.\n");
                            startButton.setEnabled(true);
                        }
                    }
            
                }
            
             
                private static void createAndShowGUI() {
                    //Create and set up the window.
                    JFrame frame = new JFrame("ProgressMonitorDemo");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
                    //Create and set up the content pane.
                    JComponent newContentPane = new ProgressMonitorTest();
                    newContentPane.setOpaque(true); //content panes must be opaque
                    frame.setContentPane(newContentPane);
            
                    //Display the window.
                    frame.pack();
                    frame.setVisible(true);
                }
                
                public void enableButton()
                {
                     startButton.setEnabled(true);
                }
            
                public static void main(String[] args) {
                    javax.swing.SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            createAndShowGUI();
                        }
                    });
                }
            }
            
            
            package components;
            
            import java.awt.Toolkit;
            import java.util.Random;
            
            import javax.swing.JComponent;
            import javax.swing.ProgressMonitor;
            import javax.swing.SwingWorker;
            
            public class TestSwingWorker extends SwingWorker<Void, Void> {
                
                 ProgressMonitor progressMonitor;
                 
                 JComponent parent;
                 
                 public void start(JComponent parent)
                 {
                        
                   progressMonitor = new ProgressMonitor(parent,
                            "Running a Long Task",
                            "", 0, 100);
                   progressMonitor.setProgress(0);
            
                  
                  super.execute();
                 }
                 @Override
                public Void doInBackground() {
                    Random random = new Random();
                    int progress = 0;
                    setProgress(0);
                    try {
                        Thread.sleep(1000);
                        while (progress < 100 && !isCancelled()) {
                            Thread.sleep(random.nextInt(1000));
                            progress += random.nextInt(10);
                            setProgress(Math.min(progress, 100));
                            System.out.println("Progress:: " + progress);
                        }
                    } catch (InterruptedException ignore) {}
                    return null;
                }
                
                   
            
                @Override
                public void done() {
                    Toolkit.getDefaultToolkit().beep();        
            
                }
            }
            
            package components;
            
            import java.awt.*;
            import java.awt.event.*;
            import javax.swing.*;
            import java.beans.*;
            import java.util.Random;
            
            public class ProgressMonitorTest2 extends JPanel
                                             implements ActionListener,
                                                        PropertyChangeListener {
            
                private ProgressMonitor progressMonitor;
                private JButton startButton;
                private JTextArea taskOutput;
                private TestSwingWorker task;
                
                
                public ProgressMonitorTest2() {
                    super(new BorderLayout());
            
                    startButton = new JButton("Another Start");
                    startButton.setActionCommand("start");
                    startButton.addActionListener(this);
            
                    taskOutput = new JTextArea(5, 20);
                    taskOutput.setMargin(new Insets(5,5,5,5));
                    taskOutput.setEditable(false);
            
                    add(startButton, BorderLayout.PAGE_START);
                    add(new JScrollPane(taskOutput), BorderLayout.CENTER);
                    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
                    
                    createAndShowGUI();
            
                }
            
            
                public void actionPerformed(ActionEvent evt) {
                    task = new TestSwingWorker();
                    task.addPropertyChangeListener(this);
                    task.start(ProgressMonitorTest2.this);
                    startButton.setEnabled(false);
                }
            
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("progress" == evt.getPropertyName() ) {
                        int progress = (Integer) evt.getNewValue();
                        String message =
                            String.format("Completed %d%%.\n", progress);
                        taskOutput.append(message);
                        if (task.isDone()) {
                            Toolkit.getDefaultToolkit().beep();
                            taskOutput.append("Task completed.\n");
                            startButton.setEnabled(true);
                        }
                    }
            
                }
            
                private void createAndShowGUI() {
                    //Create and set up the window.
                    JFrame frame = new JFrame("ProgressMonitorTest2");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
                    JComponent newContentPane = this;
                    newContentPane.setOpaque(true); //content panes must be opaque
                    frame.setContentPane(newContentPane);
            
                    frame.pack();
                    frame.setVisible(true);
                }
                
                public void enableButton()
                {
                     startButton.setEnabled(true);
                }
            
            }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
            • 3. Re: Multiple SwingWorker instances  - Progress Monitor
              843807
              Sorry, I have just sent the code I am trying. Could any one please run it and see whether I am missing something thats stopping from creating multiple threads of Worker.
              • 4. Re: Multiple SwingWorker instances  - Progress Monitor
                EJP
                Sounds like you're bitten by this bug:
                Only if (a) he is using Java 7 and (b) he is encountering a deadlock.

                I don't know about (a) but he certainly isn't getting (b).
                • 5. Re: Multiple SwingWorker instances  - Progress Monitor
                  843807
                  ejp wrote:
                  Sounds like you're bitten by this bug:
                  Only if (a) he is using Java 7
                  No, the bug was introduced in version 1.6u16. I'm runnnig 1.6u20, and it's there as well.
                  and (b) he is encountering a deadlock.
                  No, the bug may result in a deadlock. The example in the bug report does. The following small program does not. Two SwingWorkers are executed immediately after each other, but the second one cannot start its background task until the first one is done with its. Result: instead of having two tasks working in parallel, they work in serial. The example in the bug report deadlocks because the second worker is started from inside the first one.
                  import java.util.concurrent.CountDownLatch;
                  import javax.swing.SwingWorker;
                  
                  public class Bug6880336 {
                  
                      public static void main(String[] args) throws Exception {
                          Bug6880336 bug = new Bug6880336();
                          bug.start();
                          bug.latch.await();
                      }
                  
                      CountDownLatch latch = new CountDownLatch(2);
                      
                      void start() {
                          new Worker("A").execute();
                          new Worker("B").execute();
                      }
                      
                      class Worker extends SwingWorker<Void, Void> {
                  
                          private final String name;
                          
                          Worker(String name) {
                              this.name = name;
                          }
                  
                          @Override
                          protected Void doInBackground() throws Exception {
                              System.out.println("Starting worker " + name + " at " + System.currentTimeMillis());
                              Thread.sleep(5000);
                              return null;
                          }
                  
                          @Override
                          protected void done() {
                              System.out.println("Worker " + name + " is done");
                              latch.countDown();
                          }
                      }
                  }
                  The expected behavior of this program is to write
                  Starting worker A at [some timestamp]
                  Starting worker B at [more or less the same timestamp]
                  Actual behavior is:
                  Starting worker A at [some timestamp]
                  Starting worker B at [~5 seconds after first timestamp]
                  Edited by: ezo on Jul 12, 2010 9:56 PM
                  • 6. Re: Multiple SwingWorker instances  - Progress Monitor
                    843807
                    nice day,

                    nmgans @ wrote:

                    Sorry, I have just sent the code I am trying. Could any one please run it and see whether I am missing something thats stopping from creating multiple threads of Worker.
                    import java.awt.;
                    import java.awt.event.;
                    
                    import javax.swing.;
                    import java.beans.;
                    (Java import) if must be
                    import java.awt.*;
                    import java.awt.event.*;
                    
                    import javax.swing.*;
                    import java.beans.*;
                    then "your" code shold looks like as
                    import java.awt.*;
                    import java.awt.event.*;
                    import javax.swing.*;
                    import java.beans.*;
                    
                    public class ProgressMonitorTest extends JPanel implements ActionListener, PropertyChangeListener {
                    
                        private static final long serialVersionUID = 1L;
                        private JButton startButton;
                        private JButton newButton;
                        private JTextArea taskOutput;
                        private TestSwingWorker task;
                    
                        public ProgressMonitorTest() {
                            super(new BorderLayout());
                            startButton = new JButton("Start");//Create the demo's UI.
                            startButton.setActionCommand("start");
                            startButton.addActionListener(this);
                            newButton = new JButton("New Window");
                            newButton.setActionCommand("start");
                            newButton.addActionListener(new ActionListener() {
                    
                                @Override
                                public void actionPerformed(ActionEvent event) {
                                    new ProgressMonitorTest2();
                                }
                            });
                            taskOutput = new JTextArea(5, 20);
                            taskOutput.setMargin(new Insets(5, 5, 5, 5));
                            taskOutput.setEditable(false);
                            add(startButton, BorderLayout.PAGE_START);
                            add(newButton, BorderLayout.PAGE_END);
                            add(new JScrollPane(taskOutput), BorderLayout.CENTER);
                            setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
                        }
                    
                        @Override
                        public void actionPerformed(ActionEvent evt) {
                            task = new TestSwingWorker();
                            task.addPropertyChangeListener(this);
                            task.start(ProgressMonitorTest.this);
                            startButton.setEnabled(false);
                        }
                    
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("progress" == null ? evt.getPropertyName() == null : "progress".equals(evt.getPropertyName())) {
                                int progress = (Integer) evt.getNewValue();
                                String message = String.format("Completed %d%%.\n", progress);
                                taskOutput.append(message);
                                if (task.isDone()) {
                                    Toolkit.getDefaultToolkit().beep();
                                    taskOutput.append("Task completed.\n");
                                    startButton.setEnabled(true);
                                }
                            }
                        }
                    
                        private static void createAndShowGUI() {
                            JFrame frame = new JFrame("ProgressMonitorDemo");//Create and set up the window.
                            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                            JComponent newContentPane = new ProgressMonitorTest();//Create and set up the content pane.
                            newContentPane.setOpaque(true); //content panes must be opaque
                            frame.setContentPane(newContentPane);
                            frame.pack();//Display the window.
                            frame.setVisible(true);
                        }
                    
                        public void enableButton() {
                            startButton.setEnabled(true);
                        }
                    
                        public static void main(String[] args) {
                            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    
                                @Override
                                public void run() {
                                    createAndShowGUI();
                                }
                            });
                        }
                    }
                    
                    import java.awt.Toolkit;
                    import java.util.Random;
                    import javax.swing.JComponent;
                    import javax.swing.ProgressMonitor;
                    import javax.swing.SwingWorker;
                    
                    public class TestSwingWorker extends SwingWorker<Void, Void> {
                    
                        ProgressMonitor progressMonitor;
                        JComponent parent;
                    
                        public void start(JComponent parent) {
                            progressMonitor = new ProgressMonitor(parent, "Running a Long Task", "", 0, 100);
                            progressMonitor.setProgress(0);
                            super.execute();
                        }
                    
                        @Override
                        public Void doInBackground() {
                            Random random = new Random();
                            int progress = 0;
                            setProgress(0);
                            try {
                                Thread.sleep(1000);
                                while (progress < 100 && !isCancelled()) {
                                    Thread.sleep(random.nextInt(1000));
                                    progress = random.nextInt(10);
                                    setProgress(Math.min(progress, 100));
                                    System.out.println("Progress:: " + progress);
                                }
                            } catch (InterruptedException ignore) {
                            }
                            return null;
                        }
                    
                        @Override
                        public void done() {
                            Toolkit.getDefaultToolkit().beep();
                        }
                    }
                    
                    import java.awt.*;
                    import java.awt.event.*;
                    import javax.swing.*;
                    import java.beans.*;
                    
                    public class ProgressMonitorTest2 extends JPanel implements ActionListener, PropertyChangeListener {
                    
                        private static final long serialVersionUID = 1L;
                        private ProgressMonitor progressMonitor;
                        private JButton startButton;
                        private JTextArea taskOutput;
                        private TestSwingWorker task;
                    
                        public ProgressMonitorTest2() {
                            super(new BorderLayout());
                            startButton = new JButton("Another Start");
                            startButton.setActionCommand("start");
                            startButton.addActionListener(this);
                            taskOutput = new JTextArea(5, 20);
                            taskOutput.setMargin(new Insets(5, 5, 5, 5));
                            taskOutput.setEditable(false);
                            add(startButton, BorderLayout.PAGE_START);
                            add(new JScrollPane(taskOutput), BorderLayout.CENTER);
                            setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
                            createAndShowGUI();
                        }
                    
                        @Override
                        public void actionPerformed(ActionEvent evt) {
                            task = new TestSwingWorker();
                            task.addPropertyChangeListener(this);
                            task.start(ProgressMonitorTest2.this);
                            startButton.setEnabled(false);
                        }
                    
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("progress" == null ? evt.getPropertyName() == null : "progress".equals(evt.getPropertyName())) {
                                int progress = (Integer) evt.getNewValue();
                                String message = String.format("Completed %d%%.\n", progress);
                                taskOutput.append(message);
                                if (task.isDone()) {
                                    Toolkit.getDefaultToolkit().beep();
                                    taskOutput.append("Task completed.\n");
                                    startButton.setEnabled(true);
                                }
                            }
                        }
                    
                        private void createAndShowGUI() {
                            JFrame frame = new JFrame("ProgressMonitorTest2");//Create and set up the window.
                            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                            JComponent newContentPane = this;
                            newContentPane.setOpaque(true); //content panes must be opaque
                            frame.setContentPane(newContentPane);
                            frame.pack();
                            frame.setVisible(true);
                        }
                    
                        public void enableButton() {
                            startButton.setEnabled(true);
                        }
                    } 
                    • 7. Re: Multiple SwingWorker instances  - Progress Monitor
                      843807
                      nice day,

                      maybe this one can hepl you (just an example),
                      please, check the maximum/aviable number of concurrently running processes (Executors API)
                      private Executor executor = Executors.newCachedThreadPool();
                      
                      executor.execute(new OsPanelImport.MyTask("SomeString")); // 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 {
                                  //dialog.setVisible(true);
                                  //for (int i = 0; i < 1; i++) {
                                  //    Thread.sleep(200);
                                  //    publish(i);
                                  //}
                                  if (str.equals("SomeString")) {
                                      someVoid();
                                  } else if (str.equals("SomeString1")) {
                                      someVoid1();
                                  } else if (str.equals("SomeString2")) {
                                     someVoid2();
                                  } else if (str.equals("SomeString3")) {
                                     someVoid3();
                                  } else if (str.equals("SomeString4")) {
                                     someVoid4();
                                  }
                                  return null;
                              }
                      
                              @Override
                              protected void process(List<Integer> progress) {
                                  System.out.println(str + " " + progress.get(progress.size() - 1));
                              }
                      
                              @Override
                              protected void done() {
                                  //System.out.println(str + " is ready");
                                  if (str.equals("SomeString")) {
                                      someOtherVoid();
                                  }
                                  if (str.equals("SomeString1")) {
                                      someOtherVoid1();
                                  }
                                  if (str.equals("SomeString2")) {
                                      someOtherVoid2();
                                  }
                                  if (str.equals("SomeString2")) {
                                     someOtherVoid3();
                                  }
                                  if (str.equals("SomeString4")) {
                                     someOtherVoid4();
                                  }
                              }
                          }
                      
                          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;
                              }
                      
                              public void propertyChange(PropertyChangeEvent event) {
                                  if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) {
                                      System.out.println("Thread Status with Name :" + namePr + ", SwingWorker Status is " + event.getNewValue());
                                  } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) {
                                      System.out.println("Thread Status with Mame :" + namePr + ", SwingWorker Status is " + event.getNewValue());
                                  } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) {
                                      System.out.println("Thread Status with Name :" + namePr + ", SwingWorker Status is " + event.getNewValue());
                                  }
                              }
                          }
                      • 8. This Thread is now moved
                        791266
                        Note: This thread was originally posted in the Concurrency forum, but moved to this forum for closer topic alignment.
                        • 9. Re: Multiple SwingWorker instances  - Progress Monitor
                          843807
                          I ran the Bug6880336 class and it is running sequentially. I think that defeats the purpose of the Swing Worker.

                          I thought the whole idea is to run multiple processes at once and not freeze the UI.

                          Any alternatives for this?
                          • 10. Re: Multiple SwingWorker instances  - Progress Monitor
                            843807
                            nmgans wrote:
                            I ran the Bug6880336 class and it is running sequentially. I think that defeats the purpose of the Swing Worker.

                            I thought the whole idea is to run multiple processes at once and not freeze the UI.
                            That's why it is classified as a bug :)
                            Any alternatives for this?
                            If you read the comments in the bug report you'll find a couple of workarounds.