CompletableFuture와 리액티브 프로그래밍 컨셉의 기초
Executor와 스레드 풀
자바에서는 ExecutorService
를 사용해 스레드 풀을 구성할 수 있다. 구성한 스레드 풀에 작업을 제출함으로 써 작업을 수행시키는 방식이다.
- 장점
- 하드웨어 코어에 알맞은 풀을 구성해 병렬성을 만족 시킬 수 있다.
- 태스크 큐의 크기, 정책, 우선순위 등을 구성할 수 있다.
- 단점
- k개의 스레드 풀을 구성하면 작업은 동시에 최대 k개만 수행된다.
- 스레드가 종료되지 않는다면 어플리케이션은 정상적으로 종료될 수 없다.
- 스레드간의 레이스 컨디션 문제를 야기할 수 있다.
Future 형식의 API
Future<T>
를 통해 비동기 API를 사용할 수 있다.
java
1 | public class ExecutorServiceExample { |
리액티브 형식 API
함수 파라미터에 콜백형식을 넣어 태스크가 완료되면 return문이 아닌 람다 내에서 이를 호출한다.
- 리액티브 형식은 결과가 아닌 이벤트에 반응하도록 설계함으로서 예제가 적절하지는 않다.
println
이 모든 결과가 반영되기 전에 호출되는데,적절한 lock
을 통해 조정할 수 있다.
java
1 | public class CallbackStyleExample { |
적절하지 못한 Thread.sleep
Thread.sleep
을 통해 태스크를 지연시키는 방법은 자원을 점유하면서 block
상태를 유지한다. 이는 다른 태스크나 스레드가 cpu 자원을 점유하고 작업을 수행하는 것을 방해한다. 일정 시간 뒤에 다른 태스크를 수행해야 하는 경우에는 ScheduledExecutorService
를 통해 태스크를 예약 수행 할 수 있다.
java
1 | public class ScheduledExecutorServiceExample { |
CompletableFuture와 콤비네이터를 사용한 동시성
태스크 a와 b가 있고 두 태스크의 결과를 합쳐 작업을 마무리하는 코드가 있다고 하자.
java
1 | public class CFComplete { |
java
1 | public class CFCombine { |
Pub-Sub 모델
Pub-Sub 모델의 개념은 다음과 같다.
- 구독자가 구독할 수 있는 발행자
- 구독자와 발행자의 연결(구독)
- 구독을 이용한 메세지 혹은 이벤트를 전송
java
1 | public class Chapter15 { |