Java 1.5에 java.util.concurrent패키지 도입하면서 비동기 작업을 편하게 작업 할 수 있겠다.
ExecutorService
ThreadPool을 이용하여 비동기 작업들의 관리 할 수 있는 클래스
- Java 1.5 스펙
- submit 메서드를 수행하여 비동기 작업을 조회하거나 제어 할수 있는 Future 클래스를 반환
ThreadPoolExecutor와Executors의 팩토리메서드를 통해서 초기화 가능
submit
비동기 작업들을 수행하는 메서드 ( Callable, Runnable )을 파라미터로 받아 수행한다.
* Callable ( 반환 타입이 있는 함수형 인터페이스 Future의 반환 타입이된다.)
* Runnable ( 반환 타입이 없는 함수형인터페이스 )
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(() -> log.info("1번 작업"));
es.submit(() -> log.info("2번 작업"));
es.submit(() -> log.info("3번 작업"));
es.submit(() -> log.info("4번 작업"));
es.shutdown();

비동기 작업으로 수행 된다.
shutdown 과 shutdownNow 메서드
shoutdown , shutdownNow을 통해서 비동기 작업들을 종료 할 수 있다.
- shoutdown은 작업을 끝날때 까지 기다려주며
- shutdownNow은 작업이 끝날 때까지 기다려주지 않는다.
Executors의 팩토리메서드를 통해 만들 수 있는ExecutorService 종류
1. Fixed Thread Pool (Executors.newFixedThreadPool(int nThreads))
- 고정된 수의 스레드로 스레드 풀을 생성
2. Single Thread Executor (Executors.newSingleThreadExecutor())
- 단 하나의 스레드로 구성된 스레드 풀을 생성
* 여기서 블록킹 큐(대기열) 크기는 Integer.MAX 값이다.

3. Cached Thread Pool (Executors.newCachedThreadPool())
- 초기에는 스레드가 없으며, 필요에 따라 새 스레드를 생성
- 60초 동안 사용되지 않은 쓰레드는 제거가 됨
4. Scheduled Thread Pool (Executors.newScheduledThreadPool(int corePoolSize))
- 스케줄링 기능을 가진 스레드 풀을 생성
ScheduledExecutorService es = Executors.newScheduledThreadPool(2);
// 1초 후에 1번 작업 실행 하고 1분뒤에 다음 작업을 수행한다.
es.schedule(() -> log.info("1번 작업"), 1, TimeUnit.MINUTES);
es.schedule(() -> log.info("2번 작업"), 1, TimeUnit.MINUTES);
es.schedule(() -> log.info("3번 작업"), 1, TimeUnit.SECONDS);
es.schedule(() -> log.info("4번 작업"), 1, TimeUnit.SECONDS);
es.shutdown();

1 분뒤에 2번 쓰레드가 작업이 시작되었다 .
scheduleAtFixedRate 와 scheduleWithFixedDelay를 메서드를 통해 반복작업이 가능하다 .
-
scheduleAtFixedRate : 해당 작업과 무관하게 스케줄이 돌아간다
roop.scheduleAtFixedRate(() -> { log.info("scheduleAtFixedRate 반복 작업"); try {Thread.sleep(1000);} catch (InterruptedException e) {} }, 0, 1, TimeUnit.SECONDS);

- scheduleWithFixedDelay : 해당 작업 이후에 스케줄이 돌아간다.
roop.scheduleWithFixedDelay(() -> {
log.info("scheduleWithFixedDelay 반복 작업");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}, 0, 1, TimeUnit.SECONDS);

1초 지연 이후에 동작 한다.
- new ThreadPoolExecutor로 직접 생성하기
- corePoolSize : 스레드 풀에 유지할 기본쓰레드 갯수
- maxiumPollSize : 허용되는 최대 쓰레드 갯수
- keepAliveTime : 노는 쓰레드가 새 작업을 기다라는 시간
- workqueue : 대기 하고 있는 작업을 보관하는 큐
Future<T>
비동기 작업의 상태와 제어를 할수가 있는 클래스
- get()을 통해 작업을 대기하고 (블록킹) 조회한다
- isDone() 비동기 작업이 완료 되었는지 확인 한다.
- isCancelled()이 작업이 취소되었는지 여부를 확인한다.
ExecutorService es = Executors.newCachedThreadPool();
final Future<String> submit = es.submit(() -> {
Thread.sleep(1000);
log.info("1 번 작업");
return "1";
});
System.out.println("시작 done: " + submit.isDone());
final String data = submit.get();
System.out.println("작업 완료 done : " + submit.isDone());
es.shutdown();
