반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- g 단위테스트
- 병럴프로그래밍
- 안드로이드강좌
- Coroutine
- 커스텀상태
- 안드로이드
- k8s
- ReactiveProgramming
- 디자인패턴
- theming
- Rxjava
- 병렬프로그래밍
- 알고리즘
- viewmodel
- 코틀린
- 글또
- 스레드
- kotlin강좌
- 책
- 코루틴
- 회고
- 알게되는
- mockito
- Compose
- Kotlin
- 안드로이드스튜디오
- Gradle
- 테스트
- 자바
- android
Archives
- Today
- Total
선생님, 개발을 잘하고 싶어요.
자바 병렬 프로그래밍 - 2부 6장 - 작업 실행 본문
- 작업(task) 👉 추상적, 명확하게 구분된 업무 단위
- 애플리케이션 요구 사항을 작업 단위로 분할하면
- 프로그램 구조 간결
- 트랜잭션 범위 지정으로 오류 효과적 대응
- 작업 실행의 병렬성 극대화
스레드에서 작업 실행
- 작업의 범위를 어디까지로 할 건가 정해야한다.
- 완전히 독립적인 동작 👉 병렬성 보장을 위함
- 작업 스케줄링, 부하 분산(load balancing)을 하려면 작업 단위를 충분히 작게 구성
작업을 순차적으로 실행
- 가장 간단한 방법, 단일 스레드에서 작업 목록을 순차적 실행
작업마다 스레드를 직접 생성
- 작업 요청 마다 스레드를 생성한다.
- 다음과 같은 결과
- 작업 처리하는 기능이 메인 스레드와 분리 👉 서버의 응답 속도 🆙
- 동시에 여러 작업을 병렬로 처리할 수 있다 👉 서버의 처리 속도 🆙
- 프로그램이 동시에 동작할 가능성 ⬆️ 👉 스레드 안전성 필요
- 요청이 들어오는 속도보다 요청을 더 빨리 처리해야한다.
스레드를 많이 생성할 때의 문제점
- 각 작업마다 스레드 생성은 특정 상황에 엄청 많은 스레드를 만들며 다음의 단점이 발생
- 스레드 라이프 사이클 문제
- 스레드를 생성하고 제거하는 과정도 자원 소모
- 작업 부하보다 스레드 생성 부하가 더 클 수 있다.
- 자원 낭비
- 실행 중인 스레드는 메모리를 소모한다.
- CPU 갯수는 한계가 있기에 대부분의 스레드는 idle 상태
- 대기 상태 스레드 ⬆️ 👉 메모리 필요 🆙
- CPU를 사용하기 위해 스레드간 경쟁도 자원 소모
- 안정성 문제
- 시스템에 따라 최대 스레드 개수 제한
- OutOfMemory 발생할 수 있다.
- 스레드 라이프 사이클 문제
- 따라서
- 애플리케이션이 만들 수 있는 스레드 수 제한두기
- 제한된 스레드만으로 동작할 때 너무 많은 요청이 들어오는 상황에도 멈추지 않는지 테스트하기
Executor 프레임웍
- 작업(task) 👉 논리적인 업무의 단위
- 스레드 👉 특정 작업을 비동기로 동작시킬 수 있는 방법 제공
- Executor는 작업 등록과 작업 실행을 분리하는 표준
- producer-consumer 패턴에 기반
- 작업을 생성해 등록하는 클래스가 producer
- 실제로 작업을 실행하는 스레드가 consumer
- 서버 동작 특성을 Executor 설정을 변경하는 것으로 쉽게 변경 가능
실행 정책(execution policy)
- 작업 등록과 실행을 분리 👉 실행 정책을 언제든지 쉽게 변경할 수 있다.
- 작업을 어느 스레드에서 실행?
- 작업을 어떤 순서로 실행? (FIFO, LIFO, 우선순위)
- 몇 개까지 병렬 실행?
- 큐에 최대 몇 개까지 쌓아둘 수 있나?
- 작업 스케줄링 및 부하 분산은?
- 작업 실행 직전, 직후에 동작 추가?
- 실행 정책은 일종의 자원 관리 도구
- 🌟 프로그램 어디든 직접 스레드를 만들어서 작업을 시작하는 코드가 있다면 Executor 사용을 필히 고려하자.
스레드 풀(thread pool)
- 스레드 풀 👉 작업을 처리할 수 있는 스레드를 풀 형태로 관리
- 작업 큐와 밀접한 관련
- 장점
- 이전 사용 스레드 재사용 👉 스레드 계속 생성 필요 ❌ 👉 필요한 시스템 자원 ⤵️
- 스레드가 이미 만들어진 상태로 대기 👉 작업 실행 시 딜레이 ❌ 👉 전체적인 반응 속도 ⤴️
- 크기가 적절하다면 하드웨어 프로세서가 쉬지 않고 동작 가능
- 하드웨어는 쉬지 않고 동작하는 동시에, 메모리 전부 소모나 스레드 자원 경쟁 가능성 ⤵️
- Executors가 기본 제공하는 스레드 풀
- newFixedThreadPool 👉 스레드 최대 개수 제한
- newCachedThreadPool 👉 스레드 개수 제한 ❌, 쉬는 스레드를 종료
- newSingleThreadExecutor 👉 작업이 반드시 큐에 지정된 순서 순차적 처리 보장
- newScheduledThreadPool 👉 일정 시간 이후 실행, 주기적 작업 실행
- 풀 기반 전략은 안정성 측면에서 장점을 가진다.
- 성능이 떨어질 때도 점진적으로 서서히 떨어진다.
- 성능 튜닝, 실행 과정 관리, 모니터링, 로그 남기기 등 부가 작업 처리 효과적으로 할 수 있다.
Executor 동작 주기
- JVM은 모든 스레드가 종료되기 전에 종료하지 않고 대기 👉 Executor를 제대로 종료하지 않으면 JVM 자체가 종료되지 않고 대기할수도…
- 안전한 종료(graceful), 강제 종료(abrupt)
- ExecutorService 에는 동작 주기 관리 인터페이스 제공
- shutdown 👉 안전한 종료, 새로운 작업 등록 ❌, 대기 중인 작업 종료까지 기다림
- shutdownNow 👉 강제 종료, 현재 진행 중인 작업 가능한 취소, 대기 중인 작업 실행 ❌
- awaitTermination 👉 종료 상태까지 대기
- isTerminated 👉 종료 상태인가? 쿼리
지연 작업, 주기적 작업
- Timer 클래스
- 등록된 작업 실행 스레드 하나 생성 사용
- 특정 작업이 오래 실행되면 등록된 다른 TimerTask 작업이 예정된 시각에 실행 ❌
- ScheduledThreadPoolExecutor는 지연 작업, 주기적 작업마다 여러 개의 스레드 할당하므로 실행 예정 시각을 벗어나는 일 ❌
병렬로 처리할 만한 작업
예제: 순차적 페이지 렌더링
- HTML 페이지에서 텍스트 그린 다음 이미지를 차례로 다운로드 받아 비워둔 공간 채우기
결과가 나올 때까지 대기: Callable & Future
- 결과를 받아올 때 까지 시간이 많이 걸리는 작업
- 데이터베이스 쿼리
- 네트워크 데이터 받기
- 아주 복잡한 계산
- 결과를 받아서 사용하려면 Callable
- Runnable, Callable 👉 모두 작업을 추상화
- Executor에 생성한 작업은
- 생성 → 등록 → 실행 → 종료 상태를 통과한다.
- 작업을 중간에 취소할 수 있어야한다.
- Future 👉 작업의 완료, 취소 정보 확인 가능
- get 메소드를 통해 대기 가능
예제: Future를 사용해 페이지 렌더링
다양한 형태의 작업을 병렬로 처리하는 경우의 단점
- 여러 작업을 나눠 실행 👉 작업 스레드간 필요한 내용 조율에 자원 일부 소모
- 결과적으로 병렬 처리로 얻는 이득이 부하를 훨씬 넘어서야 한다.
CompletionService: Executor와 BlockingQueue의 연합
- CompletionService 👉 처리해야 할 작업이 있고, 이 작업을 모두 Executor에 등록한 후, 각 작업 결과가 나오는 즉시 그 값을 사용하고자 할 때 사용
- e.g. 이미지를 여러개 다운로드 받으면서 각 이미지가 다운로드 완료하는 순간에 화면에 랜더링 하고 싶을 때
- Callable 작업 등록 실행 가능
- take, poll 같은 큐 메소드 사용해 작업 완료되는 순간 완료된 작업의 Future instance를 받아올 수 있음
- 특정한 배치 작업을 관리하는 모습을 띤다.
요약
- 애플리케이션 작업 단위 구분 👉 개발 과정 간소화, 병렬성 ⤴️
- Executor 프레임워크 👉 작업 생성, 작업 실행 분리해서 실행 정책 수립, 원하는 실행 정책 쉽게 적용 가능
'일상 > 책 리뷰' 카테고리의 다른 글
자바 병렬 프로그래밍 - 2부 8장 - 스레드 풀 활용 (0) | 2022.06.23 |
---|---|
자바 병렬 프로그래밍 - 2부 7장 - 중단 및 종료 (0) | 2022.06.19 |
자바 병렬 프로그래밍 - 1부 5장 - 구성 단위 (0) | 2022.06.14 |
자바 병렬 프로그래밍 - 1부 4장 - 객체 구성 (0) | 2022.06.11 |
자바 병렬 프로그래밍 - 1부 3장 - 객체 공유 (0) | 2022.06.10 |
Comments