diff --git a/core-java/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java b/core-java/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java new file mode 100644 index 0000000000..58a2a5f6b4 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java @@ -0,0 +1,37 @@ +package com.baeldung.concurrent.countdownlatch; + +import java.util.List; +import java.util.concurrent.CountDownLatch; + +public class WaitingWorker implements Runnable { + + private final List outputScraper; + private final CountDownLatch readyThreadCounter; + private final CountDownLatch callingThreadBlocker; + private final CountDownLatch completedThreadCounter; + + public WaitingWorker(final List outputScraper, + final CountDownLatch readyThreadCounter, + final CountDownLatch callingThreadBlocker, + CountDownLatch completedThreadCounter) { + + this.outputScraper = outputScraper; + this.readyThreadCounter = readyThreadCounter; + this.callingThreadBlocker = callingThreadBlocker; + this.completedThreadCounter = completedThreadCounter; + } + + @Override + public void run() { + // Mark this thread as read / started + readyThreadCounter.countDown(); + try { + callingThreadBlocker.await(); + outputScraper.add("Counted down"); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + completedThreadCounter.countDown(); + } + } +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleTest.java b/core-java/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleTest.java index 484eedff24..2e77042f0b 100644 --- a/core-java/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleTest.java +++ b/core-java/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleTest.java @@ -1,6 +1,5 @@ package com.baeldung.concurrent.countdownlatch; -import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.ArrayList; @@ -8,7 +7,6 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; @@ -17,7 +15,6 @@ import static org.assertj.core.api.Assertions.assertThat; public class CountdownLatchExampleTest { @Test public void whenParallelProcessing_thenMainThreadWillBlockUntilCompletion() throws InterruptedException { - // Given List outputScraper = Collections.synchronizedList(new ArrayList<>()); CountDownLatch countDownLatch = new CountDownLatch(5); @@ -59,6 +56,41 @@ public class CountdownLatchExampleTest { final boolean result = countDownLatch.await(3L, TimeUnit.SECONDS); // Then - assertThat(result).isTrue(); + assertThat(result).isFalse(); } + + @Test + public void whenDoingLotsOfThreadsInParallel_thenStartThemAtTheSameTime() throws InterruptedException { + // Given + List outputScraper = Collections.synchronizedList(new ArrayList<>()); + CountDownLatch readyThreadCounter = new CountDownLatch(5); + CountDownLatch callingThreadBlocker = new CountDownLatch(1); + CountDownLatch completedThreadCounter = new CountDownLatch(5); + List workers = Stream + .generate(() -> new Thread(new WaitingWorker(outputScraper, readyThreadCounter, callingThreadBlocker, completedThreadCounter))) + .limit(5) + .collect(toList()); + + // When + workers.forEach(Thread::start); + readyThreadCounter.await(); // Block until workers start + outputScraper.add("Workers ready"); + callingThreadBlocker.countDown(); // Start workers + completedThreadCounter.await(); // Block until workers finish + outputScraper.add("Workers complete"); + + // Then + outputScraper.forEach(Object::toString); + assertThat(outputScraper) + .containsExactly( + "Workers ready", + "Counted down", + "Counted down", + "Counted down", + "Counted down", + "Counted down", + "Workers complete" + ); + } + } \ No newline at end of file