Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know if other threads have finished?

I have an object with a method named StartDownload(), that starts three threads.

How do I get a notification when each thread has finished executing?

Is there a way to know if one (or all) of the thread is finished or is still executing?

like image 419
Ricardo Felgueiras Avatar asked Mar 31 '09 18:03

Ricardo Felgueiras


People also ask

How do you check if a thread is still running?

Use Thread. currentThread(). isAlive() to see if the thread is alive[output should be true] which means thread is still running the code inside the run() method or use Thread.

What happens when a thread finishes?

Finishing Threads So when does a thread finish? It happens in one of two cases: all instructions in the Runnable are executed. an uncaught exception is thrown from the run method.

How do I know how many threads I have used?

Open Task Manager (press Ctrl+Shift+Esc) Select Performance tab. Look for Cores and Logical Processors (Threads)


1 Answers

There are a number of ways you can do this:

  1. Use Thread.join() in your main thread to wait in a blocking fashion for each Thread to complete, or
  2. Check Thread.isAlive() in a polling fashion -- generally discouraged -- to wait until each Thread has completed, or
  3. Unorthodox, for each Thread in question, call setUncaughtExceptionHandler to call a method in your object, and program each Thread to throw an uncaught Exception when it completes, or
  4. Use locks or synchronizers or mechanisms from java.util.concurrent, or
  5. More orthodox, create a listener in your main Thread, and then program each of your Threads to tell the listener that they have completed.

How to implement Idea #5? Well, one way is to first create an interface:

public interface ThreadCompleteListener {
    void notifyOfThreadComplete(final Thread thread);
}

then create the following class:

public abstract class NotifyingThread extends Thread {
  private final Set<ThreadCompleteListener> listeners
                   = new CopyOnWriteArraySet<ThreadCompleteListener>();
  public final void addListener(final ThreadCompleteListener listener) {
    listeners.add(listener);
  }
  public final void removeListener(final ThreadCompleteListener listener) {
    listeners.remove(listener);
  }
  private final void notifyListeners() {
    for (ThreadCompleteListener listener : listeners) {
      listener.notifyOfThreadComplete(this);
    }
  }
  @Override
  public final void run() {
    try {
      doRun();
    } finally {
      notifyListeners();
    }
  }
  public abstract void doRun();
}

and then each of your Threads will extend NotifyingThread and instead of implementing run() it will implement doRun(). Thus when they complete, they will automatically notify anyone waiting for notification.

Finally, in your main class -- the one that starts all the Threads (or at least the object waiting for notification) -- modify that class to implement ThreadCompleteListener and immediately after creating each Thread add itself to the list of listeners:

NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start();           // Start the Thread

then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed (or crashed).

Note that better would be to implements Runnable rather than extends Thread for NotifyingThread as extending Thread is usually discouraged in new code. But I'm coding to your question. If you change the NotifyingThread class to implement Runnable then you have to change some of your code that manages Threads, which is pretty straightforward to do.

like image 110
Eddie Avatar answered Oct 06 '22 17:10

Eddie