java.util.concurrent CountDownLatch explained.


import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ThreadRunner implements Runnable {
    private List<  String> eventList;
    private CountDownLatch countDownLatch;
 
    public ThreadRunner(List<  String> outputScraper, CountDownLatch countDownLatch) {
        this.eventList = outputScraper;
        this.countDownLatch = countDownLatch;
    }
 
    @Override
    public void run() {
        doSomeWork();
        eventList.add("event " + countDownLatch.getCount());
        countDownLatch.countDown();
    }

	private void doSomeWork() {
		System.out.println("do something..."   + countDownLatch.getCount());
	}
}

package com.leespace.training.thread;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class ThreadRunnerTest {
	@Test
	public void whenParallelProcessing_thenMainThreadWillBlockUntilCompletion() throws InterruptedException {
        int counter = 6;
		List<String> events = Collections.synchronizedList(new ArrayList<>());
		CountDownLatch countDownLatch = new CountDownLatch(counter);
		List<Thread> workers = Stream.generate(() -> new Thread(new ThreadRunner(events, countDownLatch))).limit(counter)
				.collect(Collectors.toList());

		workers.forEach(Thread::start);
		countDownLatch.await();
		events.add("This ia the last event");

		events.forEach(a -> System.out.println(a));

	}
}

Output:

do something…6
do something…6
do something…4
do something…3
do something…2
do something…1
event 6
event 5
event 4
event 3
event 2
event 1
This ia the last event