From comment:
All I want is that all threads must execute a certain set of code before any one of them executes the code after that set.
Use a CountDownLatch
. The javadoc describes exactly what you're needing:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
If you want to do it multiple times, use a CyclicBarrier
:
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
Here is code showing both.
Test Helper Method
private static void test(int count, Supplier<Thread> threadProducer) {
Thread[] threads = new Thread[count];
for (int i = 0; i < count; i++) {
threads[i] = threadProducer.get();
threads[i].start();
}
System.out.println("Ready");
for (int i = 0; i < count; i++)
try {
threads[i].join();
} catch (InterruptedException e) {
System.out.println(threads[i].getName() + ": " + e);
}
System.out.println("All Done");
}
CountDownLatch
class LatchThread extends Thread {
private final CountDownLatch countDownLatch;
public LatchThread(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
System.out.println(getName() + ": Started");
this.countDownLatch.countDown();
this.countDownLatch.await();
System.out.println(getName() + ": Done");
} catch (InterruptedException e) {
System.out.println(getName() + ": " + e);
}
}
}
Output shows that threads wait until all have started, i.e. until all have called countDown()
.
CountDownLatch countDownLatch = new CountDownLatch(10);
test(10, () -> new LatchThread(countDownLatch));
Thread-0: Started
Thread-4: Started
Thread-5: Started
Thread-3: Started
Thread-2: Started
Thread-1: Started
Thread-8: Started
Thread-9: Started
Thread-6: Started
Thread-7: Started
Ready
Thread-7: Done
Thread-4: Done
Thread-2: Done
Thread-0: Done
Thread-6: Done
Thread-8: Done
Thread-1: Done
Thread-9: Done
Thread-3: Done
Thread-5: Done
All Done
CyclicBarrier
class BarrierThread extends Thread {
private final CyclicBarrier cyclicBarrier;
public BarrierThread(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
System.out.println(getName() + ": Started");
if (this.cyclicBarrier != null) this.cyclicBarrier.await();
System.out.println(getName() + ": Phase 1");
if (this.cyclicBarrier != null) this.cyclicBarrier.await();
System.out.println(getName() + ": Phase 2");
if (this.cyclicBarrier != null) this.cyclicBarrier.await();
System.out.println(getName() + ": Done");
} catch (InterruptedException | BrokenBarrierException e) {
System.out.println(getName() + ": " + e);
}
}
}
Output shows that threads wait for each other before entering next phase.
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
test(10, () -> new BarrierThread(cyclicBarrier));
Thread-0: Started
Thread-5: Started
Thread-4: Started
Thread-2: Started
Thread-6: Started
Thread-1: Started
Thread-3: Started
Thread-7: Started
Thread-9: Started
Thread-8: Started
Ready
Thread-8: Phase 1
Thread-5: Phase 1
Thread-4: Phase 1
Thread-6: Phase 1
Thread-0: Phase 1
Thread-9: Phase 1
Thread-7: Phase 1
Thread-3: Phase 1
Thread-1: Phase 1
Thread-2: Phase 1
Thread-2: Phase 2
Thread-8: Phase 2
Thread-6: Phase 2
Thread-7: Phase 2
Thread-1: Phase 2
Thread-4: Phase 2
Thread-5: Phase 2
Thread-3: Phase 2
Thread-9: Phase 2
Thread-0: Phase 2
Thread-0: Done
Thread-8: Done
Thread-4: Done
Thread-2: Done
Thread-9: Done
Thread-3: Done
Thread-5: Done
Thread-1: Done
Thread-6: Done
Thread-7: Done
All Done
By comparison, without a barrier, output shows that threads don't wait for each other.
test(10, () -> new BarrierThread(null));
Thread-0: Started
Ready
Thread-4: Started
Thread-4: Phase 1
Thread-4: Phase 2
Thread-4: Done
Thread-1: Started
Thread-1: Phase 1
Thread-1: Phase 2
Thread-1: Done
Thread-5: Started
Thread-5: Phase 1
Thread-5: Phase 2
Thread-5: Done
Thread-2: Started
Thread-2: Phase 1
Thread-2: Phase 2
Thread-2: Done
Thread-3: Started
Thread-6: Started
Thread-6: Phase 1
Thread-7: Started
Thread-9: Started
Thread-9: Phase 1
Thread-8: Started
Thread-8: Phase 1
Thread-8: Phase 2
Thread-8: Done
Thread-0: Phase 1
Thread-0: Phase 2
Thread-0: Done
Thread-9: Phase 2
Thread-9: Done
Thread-7: Phase 1
Thread-7: Phase 2
Thread-7: Done
Thread-6: Phase 2
Thread-3: Phase 1
Thread-3: Phase 2
Thread-3: Done
Thread-6: Done
All Done