본문 바로가기
백엔드/Java

ExecutorService

by 개발자K씨 2023. 12. 27.

Java의 ExecutorService 클래스는 비동기 모드에서 작업 실행을 단순화하기 위해 Java 5에 도입된 java.util.concurrent 패키지에 제공되는 프레임워크입니다. 이는 Java 동시성 유틸리티의 필수 부분이며 기본 Thread 클래스에 비해 상당한 발전을 나타냅니다.

ExecutorService 이해

  • 목적: ExecutorService는 작업을 비동기적으로 관리하고 실행하도록 설계되었습니다. 이는 각 작업이 실행되는 방식의 메커니즘에서 작업 제출을 분리하여 보다 유연하고 효율적인 작업 관리를 가능하게 합니다.
  • 스레드 풀 관리: ExecutorService는 스레드 풀을 효율적으로 처리하고 작업을 할당합니다. 이 풀링 된 접근 방식은 특히 단기 작업이 많은 애플리케이션에서 각 작업에 대해 새 스레드를 생성하는 것보다 유용합니다.
  • 수명주기 관리: 작업과 서비스 자체의 수명주기를 관리하는 방법을 제공합니다. 여기에는 Excutor를 종료하는 방법이 포함되어 시스템 리소스를 순차적으로 해제할 수 있습니다.

ExecutorService의 주요 기능

  • 작업 실행: ExecutorService는 'Runnable' 및 'Callable' 작업을 실행할 수 있습니다. execute() 메서드는 Runnable 작업에 사용되고 submit()은 Callable 작업에 사용되며, 후자는 결과 검색을 위해 Future 개체를 반환합니다.
  • 스레드 풀 변형: 단일 스레드 실행기, 고정 스레드 풀, 캐시된 스레드 풀, 예약된 스레드 풀 등 다양한 유형의 스레드 풀을 사용할 수 있으며 각각 고유한 사용 사례가 있습니다.
  • 라이프사이클 작업: 'shutdown()' 및 'shutdownNow()'와 같은 메서드를 사용하면 서비스를 정상적으로 종료하거나 즉시 종료할 수 있습니다. 'isShutdown()' 및 'isTerminating()'과 같은 메서드는 실행기의 상태를 확인하는 데 도움이 됩니다.

Thread Pool 유형

  단일 스레드 실행자

단일 스레드 실행자는 Java의 실행자 프레임워크에서 Executors.newSingleThreadExecutor()를 사용하여 생성됩니다.
작업이 제출된 순서대로 순차적으로 실행되도록 하기 위해 단 하나의 스레드만 있는 스레드 풀입니다.
작업의 순차적 실행을 유지해야 하지만 기본 스레드에서 작업을 오프로드해야 하는 시나리오에 이상적입니다.

  고정 스레드 풀

Executors.newFixedThreadPool(int nThreads)로 생성된 고정 스레드 풀은 일정한 수의 스레드를 유지합니다.
모든 스레드가 사용 중이고 추가 작업이 제출되면 스레드를 사용할 수 있을 때까지 대기열에 보관됩니다.
이 유형의 풀은 알려진 고정 워크로드가 있거나 리소스 사용량을 제어하기 위해 동시 스레드 수를 제한하려는 경우 유용합니다.

  캐시된 스레드 풀

Executors.newCachedThreadPool()을 통해 시작된 캐시된 스레드 풀은 필요에 따라 새 스레드를 동적으로 생성합니다.
많은 단기 비동기 작업을 실행하는 애플리케이션에 이상적입니다.
사용되지 않은 스레드는 재사용을 위해 짧은 시간(일반적으로 60초) 동안 활성 상태로 유지됩니다. 이 기간 내에 사용하지 않으면 종료되어 풀에서 제거됩니다.

  예약된 스레드 풀

Executors.newScheduledThreadPool(int corePoolSize)를 사용하여 생성된 이 풀은 주기적으로 또는 고정된 지연 후에 실행되어야 하는 작업을 위해 설계되었습니다.
타이머 기능과 유사한 방식으로 정기적으로 또는 약간의 지연을 두고 실행되도록 작업을 예약하는 데 특히 유용합니다.

ExecutorService 구현

ExecutorService를 사용하려면 일반적으로 다음 단계를 수행합니다.

  1. Executors 클래스의 팩토리 메소드 중 하나를 사용하여 ExecutorService 인스턴스를 생성합니다.
  2. execute() 또는 submit()을 사용하여 작업을 제출합니다.
  3. shutdown() 또는 shutdownNow()를 사용하여 실행기의 수명 주기를 관리합니다.

사용 예

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(4); // 쓰레드 풀 생성

        executor.submit(() -> {
            // Task 1
            System.out.println("Running task 1");
        });

        executor.submit(() -> {
            // Task 2
            System.out.println("Running task 2");
        });

        executor.shutdown();
    }
}

주의 사항

  • 시스템 리소스를 확보하는 데 더 이상 필요하지 않은 경우 항상 서비스를 종료해야 합니다.
  • 자동 실패를 방지하기 위해 작업에서 예외를 처리해야 합니다.
  • 애플리케이션의 요구 사항에 따라 올바른 유형의 스레드 풀을 선택해야 합니다.
  • 꼭 필요한 경우가 아니면 shutdownNow()를 사용하지 마세요. 실행 중인 작업이 갑자기 중단될 수 있습니다.

결론

ExecutorService 클래스는 비동기 작업 실행을 관리하기 위한 Java의 강력한 도구입니다. 원시 스레드 관리의 복잡성을 추상화함으로써 개발자는 리소스를 효율적으로 관리하면서 비즈니스 로직 구현에 집중할 수 있습니다. ExecutorService를 올바르게 사용하면 확장 가능하고 유지 관리가 가능하며 효율적인 다중 스레드 애플리케이션이 생성됩니다.

'백엔드 > Java' 카테고리의 다른 글

자바 NIO의 동작 방식과 사용법  (1) 2024.01.04
자바 IO의 동작 방식과 사용법  (2) 2024.01.04
[lombok]@Data 주의사항  (0) 2023.12.26
lombok  (0) 2023.12.26
실수 계산이 정확하지 않은 이유  (2) 2023.12.23