Executors란?
- 고수준의 Concurrency 프로그래밍
- Thread나 Runnable처럼 Low-Level의 API를 직접 다루지 않는다.
- Thread 관리 작업을 고수준의 API에게 일을 위임한다.
- 쓰레드를 만들고 관리하는 작업을 애플리케이션에서 분리
- Executor가 Thread를 만들고 우리는 Runnable만 제공해주면 된다.
- Runnable안에 해야할 일을 정의한다.
- Thread를 만들고 실행하고, 필요없을 때 종료시키고 없애는 일련의 작업들은 Executors가 해준다.
Executors가 하는 일
- Thread 생성 : 애플리케이션이 사용할 Thread 풀을 만들어 관리
- Thread 관리 : Thread 생명 주기를 관리
- 작업 처리 및 실행 : Thread로 실행할 작업을 제공할 수 있는 API를 제공
주요 인터페이스
Executor
기본적인 타입이지만 Executor 인터페이스를 직접 쓸 일은 많지 않고, 이 타입을 상속받은 서비스 타입을 주로 사용하게 된다. execute(Runnable) 함수만 존재한다.
ExecutorService
Executor 상속받은 인터페이스로 Callable도 실행할 수 있으며, Execcutor를 종료시키거나, 여러Callable을 동시에 실행하는 등의 기능을 제공한다.
1. ExecutorService로 작업 실행/중단
public class App {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor(); //쓰레드 생성
executorService.submit(() -> System.out.prinln("Hello :" + Thread.currentThread().getName())); //쓰레드 실행
executorService.shutdown(); //처리중인 작업 기다렸다가 종료
//executorService.shutdownNow(); //처리중인 작업 기다리지 않고 당장 종료
}
}
작업을 종료하는 소스가 없으면 다음 작업이 들어올 때까지 계속하여 대기를 하기 때문에 프로세스가 죽지 않는다.
2. 쓰레드가 여러개인 풀을 만들 수 있음
public class App {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
//쓰레드가 2개인 서비스를 만들고, 작업은 5개를 모두 보낸다.
executorService.submit(getRunnable("One");
executorService.submit(getRunnable("Two");
executorService.submit(getRunnable("Three");
executorService.submit(getRunnable("Four");
executorService.submit(getRunnable("Five");
executorService.shutdown();
}
private static Runnable getRunnable(String message) {
return () -> System.out.println(message + " / " + Thread.currentThread().getName());
}
}
/* 실행 결과 (항상 동일하지는 않음) */
One / pool-1-thread-1
Two / pool-1-thread-2
Three / pool-1-thread-1
Four / pool-1-thread-1
Five / pool-1-thread-1
쓰레드가 2개이지만 작업을 5개 보내더라도 2개의 쓰레드를 번갈아가며 전부 실행 된다. 모든 쓰레드가 작업(task) 돌며 진행중일 때 남은 작업들은 blocking Queue에 쌓아놓고 대기하게 된다. 하나의 쓰레드가 작업을 마치고 나면 그 쓰레드에게 작업을 주고 실행하게 한다. 쓰레드 생성 비용이 들지 않는 것이 쓰레드 풀 사용의 장점이다.
ScheduledExecutorService
ExecutlrService를 상속받은 인터페이스로 특정 시간 이후 또는 주기적으로 작업을 실행할 수 있다.
더 공부해보자
- Fork/Join 프레임워크
- 지금까지 공부한 것은 멀티쓰레드와 관련되어있다.
- 해당 프레임워크는 멀티프로세서를 사용하는 애플리케이션을 개발할 때 유용한 프레임워크이다.
- Fork/Join 프레임워크도 ExecutorService의 구현체이다.
이 포스팅은 더 자바, Java 8 강의를 수강하며 작성되었습니다.
더 자바, Java 8 강의 | 백기선 - 인프런
백기선 | 자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합
www.inflearn.com
'Java' 카테고리의 다른 글
[Java8] CompletableFuture (0) | 2024.09.01 |
---|---|
[Java8] Callable과 Future (0) | 2024.08.29 |
[Java8] Concurrent Programming (0) | 2024.08.27 |
[Java8] Date & Time API (1) | 2024.08.12 |
[Java8] Optional API (0) | 2024.08.05 |