-
[Java]ExecutorService란?Java 2022. 7. 31. 00:01
읽기 전 미리 알고 있으면 이해하기 좋은 개념들
Thread
ThreadPool
Runnable, Callable
Future
Blocking Queue
ExecutorService란?
병렬 작업 시 여러 개의 작업을 효율적으로 처리하기 위해 제공되는 Java 라이브러리입니다.
ThreadPool을 이용하여 Task를 실행하고 관리합니다.
보통 Thread를 구현할 때 Runnable 인터페이스를 구현하거나 Thread를 상속하여 구현합니다.
이때 Thread를 new MyThread().start()로 호출할 수 있지만 java.utli.concurrent 패키지의 ExecutorService를 이용하여 실행할 수 있습니다.
ExecutorService에서 Task를 지정해주면 가지고 있는 ThreadPool을 이용하여 Task를 실행합니다.
Task는 Queue로 관리되기 때문에 ThreadPool의 Thread 개수보다 실행할 Task가 많은 경우에 미 실행된 Task는 큐에 저장되어 실행을 마친 Thread가 생길 때까지 기다립니다.
ExecutorService 초기화하는 법
1. 직접 new 키워드 사용
ExecutorService는 인터페이스이기 때문에 구현체인 ThreadPoolExecutor를 new 키워드로 초기화해서 사용합니다. (필요에 따라 다른 구현체 사용 가능)
executors 클래스를 사용하는 것보다 좀 더 세부적인 설정을 할 수 있습니다.
2. Executors 클래스에서 제공하는 Factory method를 사용
// 1. 10개 고정 사이즈의 ThreadPool 생성 ExecutorService executorService = Executors.newFixedThreadPool(10); // 2. 1개 고정 사이즈의 ThreadPool 생성 ExecutorService executorService = Executors.newSingleThreadExecutor(); // 3. 유동적으로 증가하고 줄어드는 ThreadPool 생성 ExecutorService executorService = Executors.newCachedThreadPool();
Task 할당하는 방법
1. execute() : 반환형은 void이며 Task의 실행결과나 Task의 상태를 알 수 없습니다.
executorService.execute(runnableTask);
2. submit() : Future 타입의 결괏값을 받고, 결과가 반환되어야 하기 때문에 Callable을 구현한 Task를 인자로 줍니다.
만약 Runnable로 구현한 Task라면 Future 인터페이스에 null이 반환됩니다.
Callable executorTask = () -> { return "Thread" + Thread.currentThread().getName(); }; ExecutorService executorService = Executors.newFixedThreadPool(10); for(int i=0; i<10; i++) { Future submit = executorService.submit(executorTask); System.out.println(submit.get()); } executorService.shutdown();
3. invokeAny() : Task에 Collection을 넣어서 인자로 넘겨줄 수 있습니다. 실행에 성공한 Task 중 하나의 리턴 값을 반환합니다.
String result = executorService.invokeAny(callableTasks);
4. invokeAll() : Task를 Collection에 넣어서 인자로 넘겨줄 수 있습니다. 모든 Task의 리턴값을 List<Future<>> 타입으로 반환합니다.
List<Future> futures = executorService.invokeAll(callableTasks);
ExecutorService 종료
실행한 Task가 모두 수행되어도 ExecutorService는 자동으로 종료되지 않습니다.
앞으로 들어올 Task를 처리하기 위해 Thread는 wiat 상태로 대기합니다.
종료를 위해서는 shutdown()이나 shutdownNow() 메서드를 사용해야 합니다.
1. executorService.shutdown()
실행 중인 모든 Task가 수행되면 종료합니다.
2. List<Runnable> notExcutedTasks = executorService.shutDownNow()
실행 중인 Task들을 중지하고 실행을 기다리고 있던 작업 목록을 반환합니다.
활발하게 실행 중인 작업이 종료될 때까지 기다려주지 않기 때문에 이를 위해서는 waitTermination을 사용하면 새로운 작업이 생성되는 것을 막고, 일정 시간 동안 실행 중인 Task가 완료되기를 기다립니다.
만약 일정 시간이 지난 후에도 처리되지 않은 Task에 대해서는 강제 종료시킵니다.
출처
https://simyeju.tistory.com/m/119
https://yangbox.tistory.com/28
'Java' 카테고리의 다른 글
Instant vs LocalDateTime (0) 2023.05.27 [Java] 날짜,시간과 관련된 LocalDateTime의 역사 (0) 2022.08.27 Java Lazy Evaluation이란? (0) 2022.07.24 책임 연쇄 패턴이란? (0) 2022.07.19 불변객체란 무엇인가? (0) 2022.05.29