[JAVA] ExecutorService

신명철·2022년 5월 10일
0

JAVA

목록 보기
9/14

Executors

ExecutorService 를 알아보기 전에 Executors를 알아볼 필요가 있다.

ExecutorsExecutor, ExecutorService, ScheduledExecutorService, ThreadFactory, Callable 등 멀티 쓰레드를 기반으로 실행되는 인터페이스들의 팩터리 클래스이다.

특히 ThreadPoolExecutor 생성자를 통해서 ExecutorService 구현체를 제공해준다.

ExecutorService ?

ExecutorService는 JAVA 에서 병렬 처리를 위해 제공되는 라이브러리이다.

ExecutorService 없이 병렬 처리를 구현하기 위해서는 Thread의 생성, 제거를 손수 진행해야 한다. 하지만, 이러한 일련의 과정을 ExecutorService 라는 클래스를 사용해서 쉽게 처리할 수 있다.

흔히 말하는 ThreadPool을 구현하기 매우 용이하기 때문에 ThreadPool을 생성해서 사용하고자 한다면 반드시 사용을 고려해볼 필요가 있다.

Runnable 이나 Callable 인터페이스를 구현한 Task의 실행과 종료를 수행한다. Queue로 관리되는 Task는 순차적으로 스레드에 할당된다.

ThreadPool 의 종류

  • CachedThreadPool
    • 스레드를 캐싱하는 쓰레드풀로, 스레드가 일정시간 동안 작업이 없으면 Pool에서 제거한다.
    • 스레드 수가 폭발적으로 증가할 수 있다는 단점이 있다. 스레드를 제한없이 무한정 생성하고, 해당 스레드의 작업이 없으면 Pool 에서 제거하는 방식이기 때문이다.
  • FixedThredPool
    • 고정된 갯수를 가지는 스레드풀
    • CPU 코어 수를 기준으로 스레드를 생성하면 좋은 퍼포먼스를 얻을 수 있다.
  • SingleThraedExecutor
    • 한 개의 스레드로 작업을 처리하는 스레드풀
    • 싱글 스레드의 작업을 처리할 때 고려해야 할 race condition 같은 부분들을 알아서 처리해준다
  • ScheduledThreadPool
    • 일정시간 간격으로 일을 수행시키기 위한 스레드풀
  • ForkJoinPool
    • 큰 업무를 작은 업무로 나눠 분배하고 일을 한 후에 일을 취합하는 형태
    • Task의 크기에 따라서 분할(Fork)하고, 분할된 Task가 처리되면 그것을 합쳐(Join) 리턴한다.

ExecutorService 사용법

1. ExecutorService 생성하기

  1. ThreadPoolExecutor 사용
ExecutorService executorService = new ThreadPoolExecutor(int corePoolSize, 
                                int maximumPoolSize, 
                                long keepAliveTime, 
                                TimeUnit unit, 
                                BlockingQueue<Runnable> workQueue);

ExecutorService executorService = new ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler);

ExecutorService executorService = new ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler);
  1. Executors의 정적 팩터리 메서드 사용
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService = Executors.newFixedThreadPool(int nThreads);
ExecutorService executorService = Executors.newSingleThreadExecutor();

2. Task 할당하기

Task를 할당하기 위한 메서드

  • execute()
    • 반환값이 없기 때문에 Task를 추적할 수 없다
  • submit()
    • Runnable이나 Callable 객체를 전달한다. Future 객체를 반환받기 때문에 제출한 Task의 진행 상태를 추적할 수 있다.
    • 반환된 Futurefuture.get()null이면 정상 완료된 것이다.
  • invokeAny()
    • Task를 Collection에 넣어서 인자로 넘겨준다.
    • Task들 중 하나를 수행하고 그 결과를 리턴한다. 나머지 Callable들은 취소한다.
  • invokeAll()
    • Task를 Collection에 넣어서 인자로 넘겨주고 각각의 Task들을 List<Future<>> 형태로 반환한다.

3. ExecutorService 종료

  • shutdown()
    • 실행중인 모든 Task가 수행되면 종료한다.
  • shutdownNow()
    • 실행중인 스레드들을 즉시 종료시키려고 한다. 실행 대기중인 Task 들을 중지시키고, 대기중이던 Task 리스트를 반환한다.
    • 실행중인 Task들이 끝나기를 기다리지 않고 강제적으로 중지시킨다.
  • awaitTermination()
    • 모든 Task가 완료되거나 timeout이 발생하면 종료한다.
profile
내 머릿속 지우개

0개의 댓글