ExecutorService, CountDownLatch

twocowsong·2023년 5월 15일
0

ExecutorService

Java에서 스레드 실행을 관리하는 인터페이스 입니다.
멀티스레드 애플리케이션에서 작업을 비동기적으로 실행하고 관리하는데 사용합니다.

ExecutorService인터페이스는 스레드 풀의 개념을 제공하며, 스레드를 만들고 관리하는 작업을 단순화 합니다.
애플리케이션에서 ExecutorService를 사용하면 작업을 큐에 제출하고 필요한 시점에 작업을 처리할 수 있습니다.
이를통해 성능을 향상시키고 스레드 관리에 대한 복잡성을 줄일 수 있습니다.

ExecutorService.shutdown()

shutdown 호출 시 ExecutorService에게 작업을 중지하고 리소스를 정리하도록 명령합니다.
shutdown 호출 시 ExecutorService는 새로운 작업을 거부하고, 이미 제출된 작업들은 완료될 때 까지 기다립니다.
shutdown 호출하여 ExecutorService를 명시적으로 종료하는것이 좋습니다.
이를 통해 스레드 풀 내의 모든 스레드가 종료되고, 리소스 누수나 애플리케이션의 비정상 종료를 방지 할 수 있습니다.

shutdown호출한 이후에는 ExecutorService를 재사용할 수 없습니다. 만약 재사용하려면 새로운 객체를 생성 후 사용해야합니다.

그렇기에 더욱더, shutdown을 호출하는것이 좋습니다.
이는 안정적인 애플리케이션 동작을 보장하고 리소스를 관리를 위해 필요합니다.

아래는 예제 ExecutorService소스코드입니다.

// 스레드 풀 생성 - 8개 생성
ExecutorService service = Executors.newFixedThreadPool(8);
service.execute(new Runnable() {
	@Override
    public void run() {
		// 비동기로 실행할 로직 START
        
	}
});

// 스레드 풀 종료
service.shutdown();

CountDownLatch

CountDownLatch는 ExecutorService와 함께 사용될 수 있는 동기화 유틸리티입니다.
지정된 개수의 작업이 완료될 때까지 스레드를 대기시키는데 사용됩니다.
따라서 CountDownLatch를 사용하면 ExecutorService를 더욱 효율적으로 활용할 수 있습니다.

// 스레드 풀 갯수
ExecutorService service = Executors.newFixedThreadPool(8);
CountDownLatch latch = new CountDownLatch(작업량 갯수);
service.execute(new Runnable() {
	@Override
    public void run() {
		// 비동기로 실행할 로직 START
        
        // 작업량 끝날때 마다 감소
        latch.countDown();
	}
});

latch.await(); // CountDownLatch의 카운트가 0이 될때까지 대기
service.shutdown();

일반적으로 ExecutorService를 사용할 때는 작업을 제출하고 shutdown()을 호출한 후에 작업이 완료될 때까지 await() 메서드를 호출하여 대기합니다.
비동기적으로 스레드가 작업을 진행하지만, CountDownLatch를 사용하여 작업이 완료될때까지 대기하는 것입니다.

이 방식은 작업의 비동기적 실행과 작업 완료를 효과적으로 동기화하는 데 사용될 수 있습니다.

(번외) Executors.newFixedThreadPool

Executors.newFixedThreadPool에 스레드 풀 갯수는 어떻게 산정해야할까?
너무 적은 스레드를 사용하면 작업 처리 속도가 저하될 수 있고, 너무 많은 스레드를 사용하면 시스템 리소스를 낭비하게 될 수 있습니다.

적절한 스레드 갯수를 선정하기 위해 고려해야 할 몇 가지 요소가 있습니다

  1. 작업의 성격: 작업의 종류와 특성에 따라 적절한 스레드 갯수가 달라질 수 있습니다. CPU 집약적인 작업인 경우에는 CPU 코어의 갯수에 맞게 스레드를 설정하는 것이 효율적입니다. I/O 집약적인 작업인 경우에는 I/O 작업의 대기 시간을 고려하여 적절한 스레드 수를 선택해야 합니다.

  2. 하드웨어 리소스: 시스템의 하드웨어 리소스도 고려해야 합니다. CPU 코어의 갯수, 메모리 용량, 디스크 I/O 속도 등 시스템의 성능과 제약 사항을 고려하여 스레드 갯수를 결정해야 합니다.

  3. 응답 시간 요구사항: 작업의 응답 시간 요구사항도 고려해야 합니다. 만약 작업이 신속한 응답을 요구하는 실시간 시스템이라면, 작업의 처리 속도에 맞는 스레드 갯수를 설정해야 합니다.

일반적으로는 CPU 코어의 갯수에 맞게 스레드 갯수를 설정하는 것이 일반적인 규칙입니다. 하지만 작업의 특성과 시스템의 리소스, 응답 시간 요구사항 등을 종합적으로 고려하여 조정해야 합니다. 또한, 실제로 스레드 풀을 사용하며 성능을 측정하고 튜닝하는 것도 중요합니다.

profile
생각하는 개발자

0개의 댓글