A thread can use Object.wait()
to block until another thread calls notify()
or notifyAll()
on that object.
But what if a threa
In order handle the termination of any thread from a given set without waiting for all of them to finish, a dedicated common Object (lastExited
below) can be used as monitor (wait()
and notify()
in synchronized
blocks). Further monitors are required for ensuring that at any time at most one thread is exiting (notifyExitMutex
) and at most one thread is waiting for any thread to exit (waitAnyExitMonitor
); thus the wait()
/notify()
pairs pertain always to different blocks.
Example (all process terminations are handled in the order the threads finished):
import java.util.Random;
public class ThreadMonitor {
private final Runnable[] lastExited = { null };
private final Object notifyExitMutex = new Object();
public void startThread(final Runnable runnable) {
(new Thread(new Runnable() { public void run() {
try { runnable.run(); } catch (Throwable t) { }
synchronized (notifyExitMutex) {
synchronized (lastExited) {
while (true) {
try {
if (lastExited[0] != null) lastExited.wait();
lastExited[0] = runnable;
lastExited.notify();
return;
}
catch (InterruptedException e) { }
}
}
}
}})).start();
}
private final Object waitAnyExitMutex = new Object();
public Runnable waitAnyExit() throws InterruptedException {
synchronized (waitAnyExitMutex) {
synchronized (lastExited) {
if (lastExited[0] == null) lastExited.wait();
Runnable runnable = lastExited[0];
lastExited[0] = null;
lastExited.notify();
return runnable;
}
}
}
private static Random random = new Random();
public static void main(String[] args) throws InterruptedException {
ThreadMonitor threadMonitor = new ThreadMonitor();
int threadCount = 0;
while (threadCount != 100) {
Runnable runnable = new Runnable() { public void run() {
try { Thread.sleep(1000 + random.nextInt(100)); }
catch (InterruptedException e) { }
}};
threadMonitor.startThread(runnable);
System.err.println(runnable + " started");
threadCount++;
}
while (threadCount != 0) {
Runnable runnable = threadMonitor.waitAnyExit();
System.err.println(runnable + " exited");
threadCount--;
}
}
}
It appears that in your case you're waiting for "notifications" from two different sources. You may not have to "wait" (as in normal java synchronized(object) object.wait()
) on those two objects per se, but have them both talk to a queue or what not (as the other answers mention, some blocking collection like LinkedBlockingQueue).
If you really want to "wait" on two different java objects, you might be able to do so by applying some of the principles from this answer: https://stackoverflow.com/a/31885029/32453 (basically new up a thread each to do a wait on each of the objects you're waiting for, have them notify the main thread when the object itself is notified) but it might not be easy to manage the synchronized aspects.