책/Effective Java

[이펙티브 자바] 아이템 80: 스레드보다는 실행자, 태스크, 스트림을 애용하라

2022. 7. 21. 22:14
목차
  1.  
  2. 선결론
  3. 실행자 프레임워크의 구성요소
본문은 Effective Java를 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.

 

선결론

  • 스레드를 직접 관리하면서 작업을 수행하기보다는 이미 제공된 기술들을 적극적으로 활용하자
  • 작업 큐를 손수 만들거나 스레드를 직접 다루는 일은 지양하자

 

 

실행자 프레임워크의 구성요소

  • 자바는 비동기/병렬 처리를 위해 java.util.concurrent에서 실행자 프레임워크(Executor Framework)를 제공한다
  • 실행자 프레임워크를 사용하면 스레드의 생성과 재사용을 쉽게 할 수 있기 때문에 Runnable 객체를 처리하는 데 유용하다

 

Executor 인터페이스

  • 넘겨받은 Runnable 태스크를 실행하는 역할을 한다
public interface Executor {

    void execute(Runnable command);
}
  • Excecutor 인터페이스를 사용하면 작업 단위와 실행 메커니즘이 분리된다
// 스레드를 직접 다루는 방식: 스레드가 작업 단위와 실행 메커니즘 역할을 모두 수행
// 쓰레드와 작업이 1:1
new Thread(new(RunnableTask1())).start() 
new Thread(new(RunnableTask2())).start() 


// Executor 활용: 작업 단위와 실행 메커니즘이 분리됨
// 쓰레드와 작업이 M:N, 프로그래머는 작업을 실행시키고 내부에서 적절하게 처리됨
 Executor executor = anExecutor;
 executor.execute(new RunnableTask1());
 executor.execute(new RunnableTask2());
 ...

 

 

ExecutorService 인터페이스

  • Executor를 확장한 인터페이스로서 종료를 수행하는 메서드들을 제공하고 비동기 작업의 경과를 추적하는 Future 객체를 생성할 수 있다
  • 다음은 ExecutorService의 주요 기능들이다 
    • 특정 태스크가 완료되기를 기다린다(get)
    • 태스크 모음 중 아무 것 하나가 완료되기를 기다린다(invokeAny)
    • 모든 태스크가 완료되기를 기다린다(awaitTermination)
    • 실행자 서비스가 종료하기를 기다린다(awaitTermination 메서드)
    • 완료된 태스크들의 결과를 차례로 받는다(ExecutorCompletionService 이용)
    • 태스크를 특정 시간에 혹은 주기적으로 실행하게 한다(ScheduledThreadPoolExecutor 이용)

 

Executors 클래스

  • Excutors는 쓰레드풀 생성을 할 수 있는 다양한 정적 팩터리 메서드를 제공한다
    • newCachedThreadPool, newFixedThreadPool, newScheduledThreadPool 등
    • newCachedThradPool은 요청받은 태스크들이 큐에 쌓이지 않고 즉시 스레드에 위임하게 되는데, 이 과정에서 스레드가 계속해서 생성되어 서버에 부하를 줄 수 있다
  • Executors 대신 ThreadPoolExecutor를 직접 사용하여 스레드 풀을 만들 수 있지만, 이는 스레드 풀 동작을 결정하기 위한 속성들을 일일히 세팅해줘야 하므로 번거롭다
    • 실제로 Executors 내부의 정적 팩터리 메서드들 중 몇몇은 ThreadPoolExecutor에 속성을 세팅한 후 반환한다
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>());
}

 

fork-join 태스크

  • 자바 7부터 실행자 프레임워크는 포크-조인(fork-join) 태스크를 지원한다
  • fork-join 태스크는 ForkJoinPool이라는 ExecutorService가 실행해준다(이 실행자 서비스의 생성 또한 Executors 클래스에서 지원해준다)
  • fork-join 태스크(ForkJoinTask의 인스턴스)는 작은 하위 태스크로 나뉠 수 있고, ForkJoinPool을 구성하는 스레드들이 이 태스크들을 처리하며, 일을 먼저 끝내는 스레드는 다른 스레드의 남은 태스크를 가져와 대신 처리할 수도 있다
    • 즉, CPU를 최대한 활용한다
    • ForkJoinPool을 이용해 만든 병렬 스트림(아이템 48)을 이용하면 이러한 작업을 쉽게 수행할 수 있다

 

스레드풀 동작원리

https://jenkov.com/tutorials/java-concurrency/thread-pools.html

  • 태스크가 들어오면 스레드가 바로 태스크를 수행하는 것이 아니라 작업 큐에 담는다
    • 태스크에는 Runnable과 Callable이 존재한다
    • Callable은 Runnable과 유사하지만 값을 반환하고 임의의 예외를 던질 수 있다
  • 스레드풀에 존재하는 스레드 중 작업을 마친 스레드들이 작업 큐에 담긴 태스크를 수행한다
  • 링크를 통해 위 동작을 구현하는 과정을 확인할 수 있다

 

저작자표시 비영리 (새창열림)

'책 > Effective Java' 카테고리의 다른 글

[이펙티브 자바] 아이템 88: readObject 메서드는 방어적으로 작성하라  (0) 2022.07.28
[이펙티브 자바] 아이템 72: 표준 예외를 사용하라  (0) 2022.07.16
[이펙티브 자바] 아이템 71: 필요 없는 검사 예외 사용은 피하라  (0) 2022.07.16
[이펙티브 자바] 아이템 70: 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라  (0) 2022.07.15
[이펙티브 자바] 아이템 69: 예외는 진짜 예외 상황에만 사용하라  (0) 2022.07.15
  1.  
  2. 선결론
  3. 실행자 프레임워크의 구성요소
'책/Effective Java' 카테고리의 다른 글
  • [이펙티브 자바] 아이템 88: readObject 메서드는 방어적으로 작성하라
  • [이펙티브 자바] 아이템 72: 표준 예외를 사용하라
  • [이펙티브 자바] 아이템 71: 필요 없는 검사 예외 사용은 피하라
  • [이펙티브 자바] 아이템 70: 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
코택
코택
코택
TaxFree
코택
전체
오늘
어제
  • 분류 전체보기 (369)
    • Spring (29)
      • Spring (18)
      • 스프링 핵심 원리 - 고급편 (11)
    • Spring Batch (4)
    • JPA (4)
    • CS (89)
      • 자료구조 (2)
      • 네트워크 (5)
      • 운영체제 (1)
      • 데이터베이스 (4)
      • SQL (7)
      • 알고리즘 이론 (4)
      • 알고리즘 문제 풀이 (66)
    • 웹 (28)
      • React.js (4)
      • Next.js (1)
      • Node.js (14)
      • FastAPI (4)
      • Django (5)
    • 프로그래밍 언어 (45)
      • Python (5)
      • Java + Kotlin (29)
      • JavaScript + TypeScript (11)
    • 테스트코드 (26)
      • ATDD, 클린 코드 with Spring (4)
      • 이규원의 현실 세상의 TDD: 안정감을 주는 코드.. (20)
    • 인프라 (6)
      • AWS (2)
      • Kubernetes (4)
    • 트러블슈팅 (25)
    • 책 (89)
      • Effective Java (54)
      • Effective Kotlin (14)
      • 도메인 주도 개발 시작하기: DDD 핵심 개념 정.. (11)
      • 웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 (6)
      • 도메인 주도 설계 첫걸음 (4)
    • Git (10)
    • 회고 (5)
    • etc (8)

블로그 메뉴

  • 홈
  • 방명록
  • 관리
  • GitHub
  • LinkedIn

공지사항

  • 스킨 관련

인기 글

태그

  • fastapi
  • 깊이 우선 탐색
  • 그래프 탐색
  • 브루트포스
  • 백준
  • dp
  • Git
  • 파이썬
  • http
  • 장고
  • 그래프
  • mysql
  • BOJ
  • Shortest Path
  • atdd

최근 댓글

최근 글

hELLO · Designed By 정상우.
코택
[이펙티브 자바] 아이템 80: 스레드보다는 실행자, 태스크, 스트림을 애용하라
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.