java

병렬 처리 - CountDownLatch

dev-lab 2020. 11. 16. 13:02
반응형

쓰레드를 사용해서 동시에 여러가지 작업을 하는 경우가 있다.

하지만 쓰레드는 비동기 처리이기 때문에 메인 쓰레드와 같이 작업이 진행되고 매번 처리되는 순서도 달라진다.

실행시킨 쓰레드가 모두 처리되었을 때 다시 메인 쓰레드의 동작이 실행되도록 하는 방법은 없을까 찾아보던 중

CountDownLatch 클래스를 활용하면 위의 문제를 해결할 수 있다는 걸 알게 되어 정리하는 글을 작성하게 되었다.

 

CountDownLatch는 선언 시 매개변수를 하나 받는데 해당 매개변수는 정수이다.

핵심은 countDown() 메소드와 await() 메소드인데 각각의 쓰레드에서 countDown() 메소드를 호출하면 처음 선언할 때 받은 변수의 값이 하나씩 떨어진다.

await()를 사용 시 프로그램은 CountDownLatch가 최초 선언 시 입력 받은 count가 0이 될때까지 대기상대가 된다.

쓰레드가 count를 떨어뜨려 0이 되면 프로그램이 실행되 프로그램의 sync를 맞출 수 있게 된다.


소스코드

 

import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;

public class CountDownLatchTest {
	public static void main(String[] args) throws InterruptedException {
		CountDownLatchTest t = new CountDownLatchTest();
		t.runWorkers();
	}
	
	private void runWorkers() throws InterruptedException {
		CountDownLatch countDownLatch = new CountDownLatch(5);
		IntStream.range(0, 5)
			.mapToObj(i -> new Worker(countDownLatch, i))
			.map(Thread::new)
			.forEach(Thread::start);
		
		countDownLatch.await();
		System.out.println("mainThread end");
	}
	
	private static class Worker implements Runnable{
		private CountDownLatch countDownLatch;
		private int idx;
		
		public Worker(CountDownLatch countDownLatch, int idx) {
			super();
			this.countDownLatch = countDownLatch;
			this.idx = idx;
		}

		@Override
		public void run() {
			System.out.println(idx + "-thread start");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				System.out.println(idx + "-thread end");
				countDownLatch.countDown();
			}
		}
		
	}
}

실행결과

0-thread start
4-thread start
3-thread start
2-thread start
1-thread start
3-thread end
1-thread end
2-thread end
4-thread end
0-thread end
mainThread end

개인적으로 javascript의 async await 기능과 매우 흡사하다는 느낌을 받았습니다.

반응형