Java Wait for thread to finish

234,962

Solution 1

Thread has a method that does that for you join which will block until the thread has finished executing.

Solution 2

You could use a CountDownLatch from the java.util.concurrent package. It is very useful when waiting for one or more threads to complete before continuing execution in the awaiting thread.

For example, waiting for three tasks to complete:

CountDownLatch latch = new CountDownLatch(3);
...
latch.await(); // Wait for countdown

The other thread(s) then each call latch.countDown() when complete with the their tasks. Once the countdown is complete, three in this example, the execution will continue.

Solution 3

You can use join() to wait for all threads to finish. Like below:

for (int i = 0; i < 10; i++) 
{
    Thread T1 = new Thread(new ThreadTest(i));                
    T1.start();   
    try {             
       T1.join(); 
    } catch (InterruptedException e) {
       e.printStackTrace();
    }
}

Solution 4

Better alternatives to join() method have been evolved over a period of time.

ExecutorService.html#invokeAll is one alternative.

Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list.

Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.

ForkJoinPool or Executors.html#newWorkStealingPool provides other alternatives to achieve the same purpose.

Example code snippet:

import java.util.concurrent.*;

import java.util.*;

public class InvokeAllDemo{
    public InvokeAllDemo(){
        System.out.println("creating service");
        ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        List<MyCallable> futureList = new ArrayList<MyCallable>();
        for ( int i=0; i<10; i++){
            MyCallable myCallable = new MyCallable((long)i);
            futureList.add(myCallable);
        }
        System.out.println("Start");
        try{
            List<Future<Long>> futures = service.invokeAll(futureList);  
        }catch(Exception err){
            err.printStackTrace();
        }
        System.out.println("Completed");
        service.shutdown();
    }
    public static void main(String args[]){
        InvokeAllDemo demo = new InvokeAllDemo();
    }
    class MyCallable implements Callable<Long>{
        Long id = 0L;
        public MyCallable(Long val){
            this.id = val;
        }
        public Long call(){
            // Add your business logic
            return id;
        }
    }
}

Solution 5

SwingWorker has doInBackground() which you can use to perform a task. You have the option to invoke get() and wait for the download to complete or you can override the done() method which will be invoked on the event dispatch thread once the SwingWorker completes.

The Swingworker has advantages to your current approach in that it has many of the features you are looking for so there is no need to reinvent the wheel. You are able to use the getProgress() and setProgress() methods as an alternative to an observer on the runnable for download progress. The done() method as I stated above is called after the worker finishes executing and is performed on the EDT, this allows you load the data after the download has completed.

Share:
234,962

Related videos on Youtube

Muhuri.JSON
Author by

Muhuri.JSON

Updated on May 12, 2022

Comments

  • Muhuri.JSON
    Muhuri.JSON almost 2 years

    I have a thread downloading data and I want to wait until the download is finished before I load the data. Is there a standard way of doing this?

    More Info:

    I have a Download class that gets data from a URL (Serialized POJOs). Download is Runnable and Observable. It keeps track of the bytes downloaded and download size. I have a progress bar that displays the progress to the User. The GUI observes Download to update the progress bar.

    When the POJO is downloaded I want to get it and move to the next step. Each step has to wait for the previous to finish. The problem is I cant think of a way to pause my application to wait for the download thread. Once the download is finished I want to call download.getObject() which will return the data as an object. I can then cast it and get on with the next download.

    I have a helper class that manages the URLs for download and makes all of the calls to Download. This call will call getObject and do the casting. The Gui calls helper.getUser(). helper starts the thread running and I want it to 'know' when it is finished so it can return the casted object.

    Any suggestions/examples? I am in the beginning stages of this design so I am willing to change it.

    Update:

    I followed http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get and used modal to block until the thread finished. The code was very messy and I don't like this approach. I will keep trying to find a 'clean' way to handle the workflow of the download processes.

  • Muhuri.JSON
    Muhuri.JSON over 13 years
    I tried join() but that kept the GUI from updating. The reason I used a Thread was to keep the gui updating while the download was occurring. Calling join stops that from happening.
  • akf
    akf over 13 years
    join() will work. if the GUI stops updating, you probably have to be more detailed about which threads you are joining. I wouldn't join the EDT.
  • unholysampler
    unholysampler over 13 years
    Then you need to make sure you are not calling join() in the swing thread. You can do this by creating one thread that is in charge of your download thread. This is essentially just a background worker that you can forget about. It is the worker thread that knows when the download finishes and what to do at that point. You just need to make sure edits to the swing objects are done in the swing thread.
  • JRichardsz
    JRichardsz over 6 years
    Works perfect for apps without GUI.
  • Ilya Serbis
    Ilya Serbis almost 5 years
    join() doesn't rethrow exceptions thrown inside the thread. So after join() has released current thread you don't know whether the thread finished successfully or not.
  • Johnny Five
    Johnny Five almost 5 years
    Did I understand correctly: all Callables will be executed in parallel, not subsequently?