Search code examples
javaswingjframeswingworker

Wait for thread to finish in Java


I have some code which executes a download in a separate thread, created so that the JFrame GUI will continue to update during the download. But, the purpose is completely defeated when I use Thread.join(), as it causes the GUI to stop updating. I need a way to wait for the thread to finish and still update the GUI.


Solution

  • You can have the task that does the download also fire an event to the GUI.

    For example:

    Runnable task = new Runnable() {
       public void run() {
          // do your download
    
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                // call some method to tell the GUI that the download finished.
             }
          });
       }
    };
    

    and then to run it, either use an Executor (preferred method) or a raw thread:

    executor.execute(task);
    

    or

    new Thread(task).start();
    

    As pointed out in the comments, you'd generally use a SwingWorker to do this kind of thing but you can also do the manual approach outlined above.

    SwingWorker provides a doInBackground method where you would stick your download logic in, a done method where you would stick in code to notify the GUI that the download finished and a get method to get the result of doInBackground (if there was one).

    E.g.,

    class Downloader extends SwingWorker<Object, Object> {
       @Override
       public Object doInBackground() {
           return doDownload();
       }
    
       @Override
       protected void done() {
           try { 
             frame.downloadDone(get());
           } catch (Exception ignore) {
           }
       }
    }
    
    (new Downloader()).execute();