λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

빈 ꡬ멍 μ±„μš°κΈ°

[Java] μŠ€λ ˆλ“œ 생λͺ…μ£ΌκΈ°

좜처

ChatGPT

https://www.baeldung.com/java-thread-lifecycle

 

 


μžλ°”μ˜ μŠ€λ ˆλ“œ 생λͺ…μ£ΌκΈ°λ₯Ό μ™œ μ•Œμ•„μ•Ό ν•˜λŠ”κ°€

λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°μ„ 효과적으둜 μž‘μ„±ν•˜κ³  λ””λ²„κΉ…ν•˜λŠ” 데 ν•„μˆ˜μ μ΄λ‹€.

1. μžμ› 관리

μŠ€λ ˆλ“œκ°€ μ‚¬μš©ν•˜λŠ” μ‹œμŠ€ν…œ μžμ›μ„ 효율적으둜 κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ μŠ€λ ˆλ“œμ˜ μƒνƒœλ₯Ό μ΄ν•΄ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€. 예λ₯Ό λ“€μ–΄, ν•„μš”ν•˜μ§€ μ•Šμ€ μŠ€λ ˆλ“œκ°€ 계속 μ‹€ν–‰λ˜λ©΄ μžμ› λ‚­λΉ„κ°€ λ°œμƒν•  수 μžˆλ‹€.

2. 동기화 문제 ν•΄κ²°

μŠ€λ ˆλ“œκ°€ μ–Έμ œ μ‹€ν–‰λ˜κ³  μ–Έμ œ λ©ˆμΆ”λŠ”μ§€λ₯Ό μ΄ν•΄ν•˜λ©΄ 동기화 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 도움이 λœλ‹€. 잘λͺ»λœ λ™κΈ°ν™”λŠ” λ°λ“œλ½μ΄λ‚˜ 레이슀 μ»¨λ””μ…˜κ³Ό 같은 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆλ‹€.

  • λ°λ“œλ½ Deadlock : 두 개 μ΄μƒμ˜ μŠ€λ ˆλ“œκ°€ μ„œλ‘œ μƒλŒ€λ°©μ˜ μžμ›μ„ 기닀리며 λ¬΄ν•œνžˆ λŒ€κΈ°ν•˜λŠ” μƒνƒœ. 이 μƒνƒœμ—μ„œλŠ” μ–΄λ–€ μŠ€λ ˆλ“œκ³  진행할 수 μ—†μœΌλ―€λ‘œ ν”„λ‘œκ·Έλž¨μ΄ λ©ˆμΆ”κ²Œ λœλ‹€.
    • μ˜ˆμ‹œ
      1. μŠ€λ ˆλ“œ1이 μžμ›Xλ₯Ό 잠금(lock) μƒνƒœλ‘œ λ§Œλ“€κ³  μžμ›Yλ₯Ό μ–»μœΌλ € ν•œλ‹€
      2. λ™μ‹œμ— μŠ€λ ˆλ“œ2κ°€ μžμ›Yλ₯Ό 잠금 μƒνƒœλ‘œ λ§Œλ“€κ³  μžμ›Xλ₯Ό μ–»μœΌλ € ν•œλ‹€
      3. μŠ€λ ˆλ“œ1은 μžμ›Yκ°€ ν•„μš”ν•˜κ³ ,  μŠ€λ ˆλ“œ2λŠ” μžμ›Xκ°€ ν•„μš”ν•˜λ―€λ‘œ 두 μŠ€λ ˆλ“œλŠ” μ„œλ‘œμ˜ μžμ›μ„ 기닀리며 λ¬΄ν•œ λŒ€κΈ°μ— 빠진닀.
    • λ°λ“œλ½ 방지 방법
      • μžμ›μ— λŒ€ν•œ κ³ μ •λœ νšλ“ μˆœμ„œλ₯Ό μ •ν•˜κ³ , λͺ¨λ“  μŠ€λ ˆλ“œκ°€ λ™μΌν•œ μˆœμ„œλ‘œ μžμ›μ„ νšλ“ν•˜κ²Œ ν•œλ‹€.
      • νƒ€μž„μ•„μ›ƒμ„ μ„€μ •ν•΄ μžμ›μ„ νšλ“ν•˜μ§€ λͺ»ν•˜λ©΄ ν¬κΈ°ν•˜κ³  λ‹€λ₯Έ μž‘μ—…μ„ μ‹œλ„ν•˜κ²Œ ν•œλ‹€.
  • 레이슀 μ»¨λ””μ…˜ Race Condition : 두 개 μ΄μƒμ˜ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 곡유 μžμ›μ— μ ‘κ·Όν•˜λ©΄μ„œ, κ·Έ κ²°κ³Όκ°€ μŠ€λ ˆλ“œμ˜ μ‹€ν–‰ μˆœμ„œμ— 따라 λ‹¬λΌμ§ˆ 수 μžˆλŠ” 상황을 μ˜λ―Έν•œλ‹€. 이둜 인해 μ˜ˆμƒμΉ˜ λͺ»ν•œ κ²°κ³Όκ°€ λ°œμƒν•  수 μžˆλ‹€.
    • μ˜ˆμ‹œ
      • 두 개의 μŠ€λ ˆλ“œκ°€ 같은 λ³€μˆ˜ count에 λ™μ‹œμ— μ ‘κ·Όν•΄ 값을 μ¦κ°€μ‹œν‚¨λ‹€.
      • μŠ€λ ˆλ“œ A와 Bκ°€ 각각 count 값을 읽고 1을 λ”ν•œ ν›„, 값을 λ‹€μ‹œ μ €μž₯ν•˜λ €κ³  ν•  λ•Œ μŠ€λ ˆλ“œ Aκ°€ λ¨Όμ € μ‹€ν–‰λ˜κ³ , κ·Έ λ‹€μŒ Bκ°€ μ‹€ν–‰λœλ‹€λ©΄, μ‹€μ œ κ²°κ³ΌλŠ” μ˜λ„ν–ˆλ˜ 값보닀 적게 λ‚˜μ˜¬ 수 μžˆλ‹€.
    • 레이슀 μ»¨λ””μ…˜ 방지 방법
      • 동기화 Synchronization : synchronized ν‚€μ›Œλ“œλ‚˜ ReentrantLock을 μ‚¬μš©ν•΄ 곡유 μžμ›μ— λŒ€ν•œ 접근을 ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ ν•  수 μžˆλ„λ‘ ν•œλ‹€.
        • ReentrantLock은 μžλ°”μ—μ„œ μŠ€λ ˆλ“œ 동기화λ₯Ό μœ„ν•΄ μ œκ³΅λ˜λŠ” 클래슀 쀑 ν•˜λ‚˜. synchronized ν‚€μ›Œλ“œμ™€ λΉ„μŠ·ν•˜κ²Œ, μž„κ³„ μ˜μ—­μ„ λ³΄ν˜Έν•΄ μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 곡유 μžμ›μ— μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 ν•œλ‹€.
      • μ›μžμ  μ ‘κ·Ό : AtomicInterger와 같은 클래슀λ₯Ό μ‚¬μš©ν•΄ νŠΉμ • 연산이 λΆ„ν• λ˜μ§€ μ•Šκ³  μ›μžμ μœΌλ‘œ μˆ˜ν–‰λ˜λ„λ‘ 함.
        • μ›μžμ μ΄λž€? νŠΉμ • 연산이 더 이상 λ‚˜λˆŒ 수 μ—†λŠ” λ‹¨μœ„λ‘œ μˆ˜ν–‰λœλ‹€λŠ” 것
        • μ›μžμ  μ—°μ‚°μ˜ μ€‘μš”ν•œ νŠΉμ„±
          • μ€‘λ‹¨λ˜μ§€ μ•ŠμŒ : 연산이 μ‹€ν–‰λ˜λŠ” λ™μ•ˆ λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ κ°œμž…ν•˜κ±°λ‚˜ 연산을 λ°©ν•΄ν•  수 μ—†λ‹€. 즉, 연산이 μ™„λ£Œλ  λ•ŒκΉŒμ§€λŠ” κ·Έ μƒνƒœλ₯Ό λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ μ½κ±°λ‚˜ μˆ˜μ •ν•  수 μ—†λ‹€.
          • 일관성 보μž₯ : μ›μžμ  연산은 λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ λ™μ‹œ μ ‘κ·ΌμœΌλ‘œ μΈν•œ 일관성 문제λ₯Ό λ°©μ§€ν•œλ‹€. 예λ₯Ό λ“€μ–΄ μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ 같은 λ³€μˆ˜μ— μ ‘κ·Όν•΄ 값을 λ³€κ²½ν•  λ•Œ, μ›μžμ  연산을 μ‚¬μš©ν•˜λ©΄ μ˜ˆμƒμΉ˜ λͺ»ν•œ 값이 μ„€μ •λ˜λŠ” 일이 없도둝 보μž₯ν•œλ‹€.

3. 효율적인 μŠ€λ ˆλ“œ μ‘°μž‘

μŠ€λ ˆλ“œμ˜ 생λͺ…μ£ΌκΈ°λ₯Ό μ΄ν•΄ν•˜λ©΄ ν•„μš”ν•  λ•Œ μŠ€λ ˆλ“œλ₯Ό μ€‘μ§€ν•˜κ±°λ‚˜ μž¬μ‚¬μš©ν•˜λŠ” λ“±μ˜ μ‘°μž‘μ„ 더 효율적으둜 μˆ˜ν–‰ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, WAITING, BLOCKED, TERMINATED μƒνƒœλ₯Ό μ •ν™•νžˆ μ΄ν•΄ν•˜κ³  적절히 λ‹€λ£¨λŠ” 것이 μ€‘μš”ν•˜λ‹€.

4. 디버깅 및 문제 ν•΄κ²°

μŠ€λ ˆλ“œ μƒνƒœλ₯Ό μ΄ν•΄ν•˜λ©΄ ν”„λ‘œκ·Έλž¨μ˜ 비정상적이 λ™μž‘μ΄λ‚˜ μ„±λŠ₯ 문제λ₯Ό μΆ”μ ν•˜κ³  ν•΄κ²°ν•˜λŠ” 데 도움이 λœλ‹€. 예λ₯Ό λ“€μ–΄, μŠ€λ ˆλ“œκ°€ BLOCKED μƒνƒœμ— 였래 머무λ₯Ό 경우 원인을 νŒŒμ•…ν•˜κ³  ν•΄κ²°ν•΄μ•Ό ν•  수 μžˆλ‹€.

 

μŠ€λ ˆλ“œμ˜ 생λͺ…μ£ΌκΈ°(NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED)λ₯Ό 잘 μ΄μ• ν•˜λ©΄ μ•ˆμ •μ μ΄κ³  효율적인 λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž¨μ„ κ°œλ°œν•˜λŠ” 데 μœ λ¦¬ν•˜λ‹€.

 

μžλ°”μ—μ„œ Thread의 생λͺ…μ£ΌκΈ°

μžλ°” μŠ€λ ˆλ“œλŠ” μ—¬λŸ¬ μƒνƒœλ₯Ό κ±°μΉ˜λ©΄μ„œ μ‹€ν–‰λ˜λ©°, 이λ₯Ό μŠ€λ ˆλ“œμ˜ 생λͺ…μ£ΌκΈ°(Thread Lifecycle)라고 ν•œλ‹€.

java.lang.ThreadλŠ” static State enum으둜 이 μŠ€λ ˆλ“œ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚Έλ‹€. 

1. NEW

  • μŠ€λ ˆλ“œκ°€ μƒˆλ‘œ μƒμ„±λ˜μ—ˆμ§€λ§Œ μ‹œμž‘ν•˜μ§€ μ•Šμ€ μƒνƒœ
  • Thread 객체가 μƒμ„±λ˜κ³  start() λ©”μ†Œλ“œκ°€ 호좜되기 μ „ μƒνƒœ
  • 예 : Thread thread = new Thread(runnable);

2. RUNNABLE

  • start() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ‹€ν–‰ κ°€λŠ₯ μƒνƒœκ°€ λœλ‹€.
  • 이 μƒνƒœμ—μ„œ μŠ€λ ˆλ“œλŠ” JVM에 μ˜ν•΄ μŠ€μΌ€μ€„λ§λ˜μ–΄ μ‹€μ œλ‘œ 싀행될 수 μžˆλ‹€.
  • μŠ€λ ˆλ“œ μŠ€μΌ€μ€„λ§
    • μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— μ‹€ν–‰ κ°€λŠ₯ν•œ μƒν™©μ—μ„œ CPU의 μ‹œκ°„μ„ μ–΄λ–»κ²Œ λ‚˜λˆ μ„œ 각 μŠ€λ ˆλ“œμ— 할당할지 κ²°μ •ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜. 이 과정은 JVM의 μŠ€λ ˆλ“œμ™€ 관리와 운영체제의 μŠ€μΌ€μ€„λŸ¬μ— μ˜ν•΄ 이루어진닀.
    • 운영 체제의 μŠ€μΌ€μ€„λŸ¬λŠ” λ‹€μŒμ„ κ³ λ €ν•΄ 각 μŠ€λ ˆλ“œλ₯Ό μ‹€ν–‰ν•œλ‹€
      • μš°μ„ μˆœμœ„ Priority : 각 μŠ€λ ˆλ“œλŠ” μš°μ„ μˆœμœ„κ°€ 있으며, JVM은 이 μš°μ„ μˆœμœ„λ₯Ό μ°Έμ‘°ν•΄ μƒλŒ€μ μœΌλ‘œ 높은 μš°μ„ μˆœμœ„μ˜ μŠ€λ ˆλ“œλ₯Ό λ¨Όμ € μ‹€ν–‰ν•˜λ €κ³  ν•œλ‹€.
      • 곡정성 : 운영 체제의 μŠ€μΌ€μ€„λŸ¬λŠ” κ°€λŠ₯ν•œ ν•œ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ κ³΅μ •ν•˜κ²Œ CPU μ‹œκ°„μ„ μ‚¬μš©ν•  수 μžˆλ„λ‘ κ΄€λ¦¬ν•œλ‹€.
      • μƒνƒœ μ „ν™˜ : μŠ€λ ˆλ“œκ°€ WAITING, BLOCKED와 같은 μƒνƒœμ—μ„œRUNNABLE μƒνƒœλ‘œ λ°”λ€Œμ—ˆμ„ λ•Œ, CPUμ—μ„œ μ–Έμ œ κ·Έ μ„Έλ₯΄λ“œλ₯Ό 싀행할지도 κ²°μ •ν•΄μ•Ό ν•œλ‹€.
  • RUNNABLE μƒνƒœλŠ” 운영 μ²΄μ œμ— 따라 μ‹€μ œ μ‹€ν–‰ 쀑 λ˜λŠ” μ‹€ν–‰ λŒ€κΈ° 쀑일 수 μžˆλ‹€.

3. BLOCKED

  • μŠ€λ ˆλ“œκ°€ λͺ¨λ‹ˆν„° 락을 기닀리고 μžˆμ„ λ•Œ 이 μƒνƒœκ°€ λœλ‹€.
  • λͺ¨λ‹ˆν„° 락 Monitor Lock : μžλ°”μ˜ 동기화 λ©”μ»€λ‹ˆμ¦˜μ—μ„œ 곡유 μžμ›μ— λŒ€ν•œ 접근을 μ œμ–΄ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” 잠금 μž₯치. μžλ°”μ—μ„œ 객체의 동기화 λΈ”λ‘μ΄λ‚˜ 동기화 λ©”μ†Œλ“œμ— μ ‘κ·Όν•  λ•Œ, μŠ€λ ˆλ“œλŠ” κ·Έ 객체의 λͺ¨λ‹ˆν„° 락을 νšλ“ν•΄μ•Ό ν•œλ‹€. λͺ¨λ‹ˆν„° 락을 νšλ“ν•œ κ·Έλ ˆλ“œλ§Œ ν•΄λ‹Ή μžμ›μ— μ ‘κ·Όν•  수 있으며, λ‹€λ₯Έ μŠ€λ ˆλ“œλŠ” 락이 ν•΄μ œλ  λ•Œκ°€μ§€ κΈ°λ‹€λ €μ•Ό ν•œλ‹€.
    • 동기화 λ©”μ†Œλ“œ Synchronized Method : λ©”μ„œλ“œ 전체λ₯Ό 동기화해, ν•΄λ‹Ή λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•˜λŠ” 방법
    • 동기화 블둝 Synchronized Block : μ½”λ“œμ˜ νŠΉμ • 뢀뢄을 λ™κΈ°ν™”ν•˜κ³  싢을 λ•Œ μ‚¬μš©λœλ‹€. 전체 λ©”μ†Œλ“œλ₯Ό λ™κΈ°ν™”ν•˜λŠ” 것보닀 더 μ„Έλ°€ν•˜κ²Œ 동기화λ₯Ό μ œμ–΄ν•  수 μžˆμ–΄, ν•„μš”ν•  λ•Œλ§Œ μžμ›μ„ λ³΄ν˜Έν•¨μœΌλ‘œμ¨ μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆλ‹€. 
  • 예λ₯Ό λ“€μ–΄, λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ 이미 synchronized 블둝을 μ μœ ν•˜κ³  μžˆλŠ” 경우, ν•΄λ‹Ή μžμ›μ„ μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ— BLOCKED μƒνƒœκ°€ λœλ‹€.

4. WAITING

  • μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œμ˜ μž‘μ—…μ΄ μ™Όλ£Œλ  λ•ŒκΉŒμ§€ 기닀릴 λ•Œ 이 μƒνƒœκ°€ λœλ‹€.
  • Object.wait(), Thread.join(), LockSupport.park()와 같은 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μŠ€λ ˆλ“œλŠ” WAITING μƒνƒœκ°€ λœλ‹€.
  • LockSupport.park() : μžλ°”μ—μ„œ μŠ€λ ˆλ“œλ₯Ό λŒ€κΈ° μƒνƒœλ‘œ μ „ν™˜μ‹œν‚€λŠ”λ° μ‚¬μš©λœλ‹€. 
  • WAITING μƒνƒœμ˜ μŠ€λ ˆλ“œλŠ” λͺ…μ‹œμ μœΌλ‘œ λ‹€μ‹œ ν™œμ„±ν™”λ  λ•ŒκΉŒμ§€ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. 예λ₯Ό λ“€μ–΄, notify() λ˜λŠ” notifyAll()을 ν˜ΈμΆœν•΄ λŒ€κΈ° μƒνƒœμ˜ μŠ€λ ˆλ“œλ₯Ό 깨울 수 μžˆλ‹€.

5. TIMED_WAITING

  • μŠ€λ ˆλ“œκ°€ 일정 μ‹œκ°„ λ™μ•ˆ λŒ€κΈ°ν•  λ•Œ 이 μƒνƒœκ°€ λœλ‹€.
  • sleep(long millis), wait(long timeout), join(long millis) λ“±μ˜ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄ 일정 μ‹œκ°„μ΄ μ§€λ‚œ ν›„ λ‹€μ‹œ μ‹€ν–‰ κ°€λŠ₯ν•˜κ²Œ λœλ‹€.
  • TIMED_WAITING μƒνƒœμ—μ„œλŠ” μ§€μ •λœ μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ μžλ™μœΌλ‘œ μ‹€ν–‰ κ°€λŠ₯ν•œ μƒνƒœλ‘œ λŒμ•„κ°„λ‹€. 

6. TERMINATED

  • μŠ€λ ˆλ“œκ°€ μž‘μ—…μ„ 마치고 μ’…λ£Œλœ μƒνƒœ
  • μŠ€λ ˆλ“œμ˜ run() λ©”μ†Œλ“œκ°€ μ •μƒμ μœΌλ‘œ μ’…λ£Œλ˜κ±°λ‚˜ μ˜ˆμ™Έκ°€ λ°œμƒν•΄ μ’…λ£Œλ  λ•Œ 이 μƒνƒœκ°€ λœλ‹€.
  • 이 μƒνƒœμ—μ„ λŠ μŠ€λ ˆλ“œκ°€ 더 이상 μ‹€ν–‰λ˜μ§€ μ•ŠμœΌλ©°, λ‹€μ‹œ μ‹œμž‘ν•  수 μ—†λ‹€.

 

μŠ€λ ˆλ“œ 생λͺ…μ£ΌκΈ° μ˜ˆμ‹œ

public class ThreadLifeCycleExample extends Thread {
    public void run() {
        System.out.println("Thread is running...");
        try {
            Thread.sleep(1000); // TIMED_WAITING μƒνƒœλ‘œ 이동
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread has finished executing.");
    }

    public static void main(String[] args) {
        ThreadLifeCycleExample thread = new ThreadLifeCycleExample(); // NEW μƒνƒœ
        thread.start(); // RUNNABLE μƒνƒœλ‘œ 이동

        try {
            thread.join(); // ν˜„μž¬ μŠ€λ ˆλ“œκ°€ thread의 μ’…λ£Œλ₯Ό κΈ°λ‹€λ¦¬λ―€λ‘œ WAITING μƒνƒœ
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread has finished executing.");
    }
}