This can be done in various ways, for example, using the general Semaphore:
public static class Task implements Runnable {
Semaphore s;
String name;
public Task(Semaphore s, String name) {
this.s = s;
this.name = name;
}
@Override
public void run() {
System.out.println(name + " waiting");
try {
s.acquire();
System.out.println(name + " continuing");
} catch (InterruptedException e) {
System.out.println("Interrupted while waiting");
}
}
}
Semaphore :
Semaphore s = new Semaphore(0);
new Thread(new Task(s, "Task A")).start();
new Thread(new Task(s, "Task B")).start();
Thread.sleep(1000);
s.release(2); // release 2 permits to allow both threads continue
:
Task A waiting
Task B waiting
Task A continuing // after 1 second
Task B continuing