ThreadPoolExecutor, TaskExecutor

ThreadPoolExecutor (java)

Javaμ—μ„œλŠ” ExecutorsλΌλŠ” μœ ν‹Έλ¦¬ν‹° 클래슀(νŒ©ν† λ¦¬)λ₯Ό 톡해 ThreadPoolExecutorλ₯Ό λ‹€μ–‘ν•œ 사전 μ„€μ •μœΌλ‘œ 생성할 수 μžˆλ‹€. μ΄λŠ” νŽΈλ¦¬ν•˜μ§€λ§Œ, 운영 ν™˜κ²½μ—μ„œλŠ” 잠재적인 μœ„ν—˜μ„ λ‚΄ν¬ν•˜κ³  μžˆμ–΄ 각 νŠΉμ§•μ„ λͺ…ν™•νžˆ μ΄ν•΄ν•˜κ³  μ‚¬μš©ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€κ³  νŒλ‹¨λœλ‹€.

1. Executors.newFixedThreadPool

인자(nThreads)둜 μ£Όμ–΄μ§„ 개수만큼 μŠ€λ ˆλ“œλ₯Ό κ°€μ§€λŠ” κ³ μ • μŠ€λ ˆλ“œ 풀을 μƒμ„±ν•œλ‹€. μ‹œμŠ€ν…œμ˜ λ¦¬μ†ŒμŠ€λ₯Ό μ˜ˆμΈ‘ν•˜κ³  μ œμ–΄ν•˜λŠ” 데 μ‚¬μš©λ¨.

// Executors.newFixedThreadPool(nThreads)의 μ‹€μ œ λ‚΄λΆ€ μ½”λ“œ
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads, // core와 maxκ°€ 동일
                                  0L, TimeUnit.MILLISECONDS, // keepAliveTime은 0
                                  new LinkedBlockingQueue<Runnable>()); // λŒ€κΈ° 큐
}

νŠΉμ§•:

  • nTreads개의 μŠ€λ ˆλ“œλ§Œ μƒμ„±ν•΄μ„œ μ‚¬μš©

  • λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μž‘μ ‘μ„ μˆ˜ν–‰ 쀑일 λ•Œ, μΆ”κ°€λ‘œ λ“€μ–΄μ˜¨ μž‘μ—…μ€ λŒ€κΈ° νμ—μ„œ λ¬΄ν•œμ • λŒ€κΈ°

  • μŠ€λ ˆλ“œκ°€ μž‘μ—…μ„ λ§ˆμ³λ„ ν’€μ—μ„œ μ œκ±°λ˜μ§€ μ•Šκ³  계속 μž¬μ‚¬μš©

μœ„ν—˜μ„±:

  • LinkedBlockingQueue의 크기λ₯Ό μ§€μ •ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— 큐의 μ΅œλŒ€ ν¬κΈ°λŠ” Integer.MAX_VALUEκ°€ λœλ‹€.

  • 처리 속도보닀 νμž‰ 속도가 λΉ λ₯΄λ©΄ λŒ€κΈ° 큐가 λ¬΄ν•œλŒ€λ‘œ μ»€μ Έμ„œ OOM λ°œμƒ κ°€λŠ₯성이 있음

2. Executors.newCachedFixedThreadPool

ν•„μš”μ— 따라 μŠ€λ ˆλ“œλ₯Ό μœ λ™μ μœΌλ‘œ μƒμ„±ν•˜κ³ , μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” μŠ€λ ˆλ“œλŠ” μžλ™μœΌλ‘œ μ œκ±°ν•˜λŠ” 동적 μΊμ‹œ μŠ€λ ˆλ“œ 풀을 μƒμ„±ν•œλ‹€.

νŠΉμ§•:

  • SynchronousQueueλŠ” μž‘μ—…μ„ μ €μž₯ν•˜μ§€ μ•Šκ³  λ°”λ‘œ 유휴 μŠ€λ ˆλ“œμ— μ „λ‹¬ν•˜λŠ” 역할을 함.

  • λ§Œμ•½ 유휴 μŠ€λ ˆλ“œκ°€ μ—†μœΌλ©΄ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό 생성

  • μŠ€λ ˆλ“œ 개수 μƒν•œμ„ μ΄ μ—†μ–΄μ„œ, μš”μ²­μ΄ λ§Žμ•„μ§€λ©΄ κ·Έ 만큼 μŠ€λ ˆλ“œκ°€ λŠ˜μ–΄λ‚¨.

  • μ‹€ν–‰ μ‹œκ°„μ΄ 짧은 μˆ˜λ§Žμ€ μž‘μ—…μ„ λŒ€κΈ° 없이 λΉ λ₯΄κ²Œ μ²˜λ¦¬ν•˜λŠ” 데 μ ν•©ν•˜κ²Œ μ‚¬μš©λ¨

μœ„ν—˜μ„±:

  • μš”μ²­μ΄ ν­μ£Όν•˜κ±°λ‚˜ κ°œλ³„ μž‘μ—…μ˜ 처리 μ‹œκ°„μ΄ κΈΈμ–΄μ§€λ©΄, μ¦κ°€ν•˜λŠ” μŠ€λ ˆλ“œ 수 λ•Œλ¬Έμ— OOM λ°œμƒ κ°€λŠ₯성이 있음

3. Executors.newSingleThreadExecutor

단, ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§ŒμœΌλ‘œ μž‘μ—…μ„ μ²˜λ¦¬ν•˜μ—¬, μž‘μ—…μ˜ 순차적 싀행을 보μž₯ν•˜λŠ” μŠ€λ ˆλ“œ 풀이닀.

νŠΉμ§•:

  • 였직 ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— μž‘μ—…λ“€μ΄ FIFO μˆœμ„œλŒ€λ‘œ 싀행됨을 보μž₯ν•œλ‹€.

  • μ—¬λŸ¬ κ³³μ—μ„œ λ°œμƒν•œ 이벀트λ₯Ό μˆœμ„œλŒ€λ‘œ μ²˜λ¦¬ν•  λ•Œ μœ μš©ν•¨. (ex: 순차적 둜그, μƒνƒœ 데이트 λ“±)

μœ„ν—˜μ„±:

  • FixedPoolκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ, λŒ€κΈ° 큐가 λ¬΄ν•œλŒ€λ‘œ 컀져 OOM λ°œμƒ κ°€λŠ₯성이 있음

ThreadPoolTaskExecutor (Spring)

Executors νŒ©ν† λ¦¬μ˜ νŽΈλ¦¬ν•¨κ³Ό ThreadPoolExecutor 직접 μƒμ„±μ˜ μ œμ–΄λ ₯을 λͺ¨λ‘ κ°–μΆ”κ³ , Spring μƒνƒœκ³„μ— ν•„μš”ν•œ μΆ”κ°€ κΈ°λŠ₯κΉŒμ§€ λ”ν•œ Spring ν™˜κ²½μ˜ ν‘œμ€€ μŠ€λ ˆλ“œ ν’€ κ΅¬ν˜„μ²΄μ΄λ‹€.

νŠΉμ§•:

λ¦¬μ†ŒμŠ€ μ•ˆμ •μ„±

  • λŒ€κΈ° 큐의 μ΅œλŒ€ 크기λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ œν•œν•˜μ—¬, λ¬΄ν•œ 큐 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€.

  • μ΅œλŒ€ μŠ€λ ˆλ“œ 수λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ œν•œν•  수 μžˆμ–΄μ„œ λ™μ μœΌλ‘œ μ¦κ°€ν•˜λŠ” μŠ€λ ˆλ“œ 개수λ₯Ό μ œμ–΄ν•  수 μžˆλ‹€.

  • ThreadPoolκ³Ό Queueκ°€ 가득 찼을 λ•Œ κ±°λΆ€ 정책을 μ •μ˜ν•  수 μžˆλ‹€.

μžλ™ 생λͺ…μ£ΌκΈ° 관리

  • Spring μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ  λ•Œ, λ“±λ‘λœ Bean의 shutdown() λ©”μ†Œλ“œλ₯Ό μžλ™μœΌλ‘œ ν˜ΈμΆœν•œλ‹€.

  • μŠ€ν”„λ§ 빈으둜 κ΄€λ¦¬λ˜κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ μ„œλΉ„μŠ€μ— μ‰½κ²Œ μ˜μ‘΄μ„± μ£Όμž…(DI)이 κ°€λŠ₯ν•˜λ‹€.

  • @Async("name")와 같이, μ—¬λŸ¬ μŠ€λ ˆλ“œ 풀을 μš©λ„λ³„λ‘œ μ •μ˜ν•˜κ³  이름을 μ§€μ •ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆμ–΄μ„œ, μž‘μ—… 성격에 따라 리둜슀λ₯Ό κ²©λ¦¬ν•˜κ³  κ΄€λ¦¬ν•˜κΈ° μš©μ΄ν•˜λ‹€.

Last updated