작업 실행
작업(task) > 추상적, 명확하게 구분된 업무 단위
애플리케이션 요구 사항
스레드에서 작업 실행
작업의 범위를 어디까지로 할 건가 정해야한다.
작업을 순차적으로 실행 > 가장 간단한 방법, 단일 스레드에서 작업 목록을 순차적 실행
작업마다 스레드를 직접 생성 > 작업 요청 마다 스레드를 생성한다.
요청이 들어오는 속도보다 요청을 더 빨리 처리해야한다.
스레드를 많이 생성할 때의 문제점
각 작업마다 스레드 생성은 특정 상황에 엄청 많은 스레드를 만들며 다음의 단점이 발생
스레드 라이프 사이클 문제
자원 낭비
안정성 문제
애플리케이션이 만들 수 있는 스레드 수 제한두기 제한된 스레드만으로 동작할 때 너무 많은 요청이 들어오는 상황에도 멈추지 않는지 테스트하기
Executor
실행 정책(execution policy)
작업 등록과 실행을 분리하여실행 정책을 언제든지 쉽게 변경할 수 있다.
실행 정책은 일종의 자원 관리 도구 프로그램 어디든 직접 스레드를 만들어서 작업을 시작하는 코드가 있다면 Executor 사용을 필히 고려하자.
스레드 풀(thread pool)
작업을 처리할 수 있는 스레드를 풀 형태로 관리
작업 큐와 밀접한 관련
장점
Executors가 기본 제공하는 스레드 풀
풀 기반 전략은 안정성 측면에서 장점을 가진다. 성능이 떨어질 때도 점진적으로 서서히 떨어진다. 성능 튜닝, 실행 과정 관리, 모니터링, 로그 남기기 등 부가 작업 처리 효과적으로 할 수 있다.
Executor 동작 주기
JVM은 모든 스레드가 종료되기 전에 종료하지 않고 대기 👉 Executor를 제대로 종료하지 않으면 JVM 자체가 종료되지 않고 대기할수도…
안전한 종료(graceful), 강제 종료(abrupt)
지연 작업, 주기적 작업
Timer 클래스
등록된 작업 실행 스레드 하나 생성 사용 특정 작업이 오래 실행되면 등록된 다른 TimerTask 작업이 예정된 시각에 실행 ❌ ScheduledThreadPoolExecutor는 지연 작업, 주기적 작업마다 여러 개의 스레드 할당하므로 실행 예정 시각을 벗어나는 일 ❌
병렬로 처리할 만한 작업
순차적 페이지 렌더링 > HTML 페이지에서 텍스트 그린 다음 이미지를 차례로 다운로드 받아 비워둔 공간 채우기
결과가 나올 때까지 대기: Callable & Future
결과를 받아올 때 까지 시간이 많이 걸리는 작업
결과를 받아서 사용하려면 Callable
Runnable, Callable > 모두 작업을 추상화
Executor에 생성한 작업은
Future > 작업의 완료, 취소 정보 확인 가능 get 메소드를 통해 대기 가능
Future를 사용해 페이지 렌더링
다양한 형태의 작업을 병렬로 처리하는 경우의 단점
CompletionService: Executor와 BlockingQueue의 연합
CompletionService : 처리해야 할 작업이 있고, 이 작업을 모두 Executor에 등록한 후, 각 작업 결과가 나오는 즉시 그 값을 사용하고자 할 때 사용
Last updated