Search code examples
javamultithreadingswinginvokelater

In Java using Swing, how can I know when all threads launched with invokeLater have finished?


Inside a createAndShowGUI() method called by javax.swing.SwingUtilities.invokeLater like this...:

public static void main(String[] args) { 
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() { 
            createAndShowGUI(); 
        } 
    }); 
}

...I have the following piece of code which launches multiple threads with invokeLater where each threads increments the value of progBar when it is ran:

int times = 20;

for(int x = 0; x < times; x = x+1) {
        new Thread("T") {
                public void run() {

                        try {                                              
                            Thread.sleep(5000);

                        } catch(InterruptedException ex) {
                            Thread.currentThread().interrupt();
                        }

                        SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                        progBar.setValue(progBar.getValue()+1);
                                }
                        });

                }

        }.start();

}

How can I know where all the threads are finished? If I use a counter inside invokeLater I think I will I run into race conditions.. So what is the right way to do it? Should I use a mutex? Are there some facilities provided by Swing to this purpose? Thanks.

I have implemented the code in this way according to http://www.java2s.com/Code/Java/Threads/InvokeExampleSwingandthread.htm


Solution

  • The Runnables you pass to invokeLater are all executed on the single Event Dispatch Thread. Due to the fact that they are all sent by different threads there is no particular order but they are executed one after another.

    So once you have fixed your code by moving the UI updates into the Runnable you are passing to invokeLater you can use Swings notification mechanism to get informed about the finishing of the jobs:

    final int end=progBar.getValue() + times;
    progBar.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        if(progBar.getValue()==end) {
          System.out.println("all jobs finished");
        }
      }
    });
    for(int x = 0; x < times; x = x+1) {
      new Thread("T") {
        public void run() {
          try {                                              
              Thread.sleep(5000);
          } catch(InterruptedException ex) {
              Thread.currentThread().interrupt();
          }
          SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                    progBar.setValue(progBar.getValue()+1);
                  }
          });
        }
      }.start();