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

[Java] Thread의 stop()κ³Ό interrupt()의 비ꡐ

⭐⭐기둝 2024. 10. 1. 06:03

좜처

ChatGPT

μžλ°” 8 μ†ŒμŠ€ μ½”λ“œ

https://cano721.tistory.com/165

 

[Java] μ“°λ ˆλ“œ 5 - μ“°λ ˆλ“œμ˜ μ‹€ν–‰μ œμ–΄(sleep, interrupt, join, yield)

μ“°λ ˆλ“œμ˜ μŠ€μΌ€μ€„λ§ κ΄€λ ¨ λ©”μ„œλ“œ λ©”μ„œλ“œ μ„€ λͺ… static void sleep(long millis) static void sleep(long millis, int nanos) μ§€μ •λœ μ‹œκ°„(μ²œλΆ„μ˜ 1초 λ‹¨μœ„)λ™μ•ˆ μ“°λ ˆλ“œλ₯Ό μΌμ‹œμ •μ§€μ‹œν‚¨λ‹€. μ§€μ •ν•œ μ‹œκ°„μ΄ μ§€λ‚˜κ³  λ‚˜λ©΄,

cano721.tistory.com

 

 


μžλ°”μ˜ Thread.stop() λ©”μ†Œλ“œλŠ” μŠ€λ ˆλ“œλ₯Ό κ°•μ œλ‘œ μ’…λ£Œμ‹œν‚€λŠ” μœ„ν•œ ν•¨μˆ˜λ‘œ deprecated 됐닀. stop()의 문제 해결을 μœ„ν•΄ interrupt() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄ μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œν•˜λŠ” 것을 ꢌμž₯ν•œλ‹€.

 

 

Thread.stop() μ†ŒμŠ€ μ½”λ“œ 뢄석

Thread.stop()은 μŠ€λ ˆλ“œμ— κ°•μ œλ‘œ ThreadDeath μ˜ˆμ™Έλ₯Ό 던져 μ’…λ£Œμ‹œν‚¨λ‹€.

@Deprecated
public final void stop() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        checkAccess();
        if (this != Thread.currentThread()) {
            security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
        }
    }
    // A zero status value corresponds to "NEW", it can't change to
    // not-NEW because we hold the lock.
    if (threadStatus != 0) {
        resume(); // Wake up thread if it was suspended; no-op otherwise. 
        // μŠ€λ ˆλ“œκ°€ μ •μ§€ μƒνƒœλ©΄ 재개
    }
    // The VM can handle all thread states
    // λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œλ₯Ό 톡해 μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œμ‹œν‚΄
    stop0(new ThreadDeath());
}

 

  • stop0() λ©”μ†Œλ“œλŠ” λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œμ΄λ‹€. 이 λ©”μ†Œλ“œλŠ” JVM λ ˆλ²¨μ—μ„œ κ°•μ œλ‘œ μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œν•˜λŠ” λͺ…령을 μˆ˜ν–‰ν•œλ‹€.
  • ThreadDeath μ˜ˆμ™ΈλŠ” μŠ€λ ˆλ“œμ— λ˜μ Έμ§€κ³ , 이 μ˜ˆμ™Έλ₯Ό catchν•˜μ§€ μ•ŠμœΌλ©΄ μŠ€λ ˆλ“œκ°€ μ’…λ£Œλœλ‹€. 이 방식은 맀우 κ°•μ œμ μ΄κΈ° λ•Œλ¬Έμ— μŠ€λ ˆλ“œκ°€ λ¦¬μ†ŒμŠ€λ₯Ό 적절히 ν•΄μ œν•  기회λ₯Ό κ°–μ§€ λͺ»ν•œλ‹€.

문제점

  • μŠ€λ ˆλ“œλ₯Ό κ°•μ œλ‘œ μ€‘λ‹¨μ‹œμΌœ(μŠ€λ ˆλ“œλ₯Ό λ°”λ‘œ TERMINATED μƒνƒœλ‘œ μ „ν™˜μ‹œμΌœ) 잠금이 ν•΄μ œλ˜μ§€ μ•Šκ±°λ‚˜ μžμ›μ΄ μ œλŒ€λ‘œ ν•΄μ œλ˜μ§€ μ•Šμ„ 수 μžˆλ‹€.
    • μŠ€λ ˆλ“œλ₯Ό μ¦‰μ‹œ μ’…λ£Œμ‹œν‚€λ―€λ‘œ, μŠ€λ ˆλ“œκ°€ μžμ›μ„ μ‚¬μš©ν•˜κ±°λ‚˜ 곡유 μžμ›μ„ κ°±μ‹  쀑일 λ•Œ 이λ₯Ό κ°‘μžκΈ° λ©ˆμΆ”λ©΄ λ°μ΄ν„°μ˜ 일관성이 깨질 수 μžˆλ‹€.
    • μŠ€λ ˆλ“œκ°€ μž„κ³„ μ˜μ—­μ—μ„œ 곡유 μžμ›μ„ μˆ˜μ • μ€‘μ΄μ—ˆλ‹€λ©΄, κ°‘μž‘μŠ€λŸ½κ²Œ μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λ©΄μ„œ λͺ¨λ‹ˆν„° 락이 ν•΄μ œλ˜μ§€ μ•Šκ±°λ‚˜ μžμ› λˆ„μˆ˜κ°€ λ°œμƒν•  수 μžˆλ‹€.
  • ThreadDeath μ˜ˆμ™Έλ₯Ό λ˜μ§€κΈ° λ•Œλ¬Έμ— 예기치 μ•Šμ€ μƒνƒœλ‘œ μ’…λ£Œλ  수 μžˆλ‹€.

 

Thread.interrupt() μ†ŒμŠ€ μ½”λ“œ 뢄석

Thread.interrupt()λŠ” μŠ€λ ˆλ“œμ— μΈν„°λŸ½νŠΈ μ‹ ν˜Έλ₯Ό 보내 쀑단 μš”μ²­μ„ ν•œλ‹€. 이 λ©”μ†Œλ“œλŠ” μŠ€λ ˆλ“œκ°€ 응닡할 수 μžˆλ„λ‘ μΈν„°λŸ½νŠΈ μƒνƒœλ₯Ό μ„€μ •ν•΄ λ‘λŠ” 역할을 ν•œλ‹€. 

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess(); // μ ‘κ·Ό κΆŒν•œ 검사 
    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
        	// λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œλ₯Ό 톡해 μΈν„°λŸ½νŠΈ μ‹€ν–‰
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0(); // λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œλ₯Ό 톡해 μΈν„°λŸ°νŠΈ μƒνƒœ μ„€μ •
}
  • interrupt()λŠ” μΈν„°λŸ½νŠΈ μƒνƒœλ₯Ό μ„€μ •ν•˜κ±°λ‚˜, ν˜„μž¬ μŠ€λ ˆλ“œκ°€ 잠겨 μžˆλŠ” 경우 이λ₯Ό ν•΄μ œν•  수 μžˆλ„λ‘ ν•œλ‹€.
  • interrrupt0()은 λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œλ‘œ, JVMμ—μ„œ μŠ€λ ˆλ“œμ˜ μΈν„°λŸ½νŠΈ μƒνƒœλ₯Ό λ³€κ²½ν•˜λ„λ‘ ν•œλ‹€.
  • μΈν„°λŸ½νŠΈκ°€ 호좜된 μŠ€λ ˆλ“œλŠ” 슀슬둜 μΈν„°λŸ½νŠΈ μƒνƒœλ₯Ό ν™•μΈν•˜κ³  ν•„μš”ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ©° μ’…λ£Œ μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.

 

μŠ€λ ˆλ“œ μƒνƒœμ— λ”°λ₯Έ interrupt() λ™μž‘ 

  • μŠ€λ ˆλ“œκ°€ sleep(), wait(), join()κ³Ό 같은 λŒ€κΈ° μƒνƒœ(TIMED_WAITING, WAITING)μ—μ„œ μΈν„°λŸ½νŠΈ μ‹ ν˜Έλ₯Ό λ°›μœΌλ©΄, InterruptedException μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©°, μŠ€λ ˆλ“œλŠ” λŒ€κΈ° μƒνƒœμ—μ„œ λ²—μ–΄λ‚˜κ²Œ λœλ‹€. μ΄λ•Œ μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•΄ μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œν•˜κ±°λ‚˜ λ‹€λ₯Έ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.
  • μŠ€λ ˆλ“œκ°€ μ‹€ν–‰ κ°€λŠ₯ μƒνƒœ(RUNNABLE)에 μžˆμ„ λ•Œ interrupt()κ°€ 호좜되면, μŠ€λ ˆλ“œλŠ” μΈν„°λŸ½νŠΈ ν”Œλž˜κ·Έκ°€ 섀정될 뿐 싀행이 μ¦‰μ‹œ μ€‘λ‹¨λ˜μ§€λŠ” μ•ŠλŠ”λ‹€. ν•΄λ‹Ή μŠ€λ ˆλ“œ λ‚΄μ—μ„œ Thread.interrupted() λ©”μ†Œλ“œλ₯Ό 톡해 μΈν„°λŸ½νŠΈ ν”Œλž˜κ·Έλ₯Ό ν™•μΈν•˜κ³ , ν”Œλž˜κ·Έκ°€ μ„€μ •λœ 경우 μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œν•˜κ±°λ‚˜ μ μ ˆν•œ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

 

interrupt()둜 μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œν•˜κΈ°

1. 반볡문 μ•ˆμ—μ„œ isInterrupted()λ₯Ό 톡해 interrupt() 호좜 μ—¬λΆ€λ₯Ό 확인해 νƒˆμΆœν•œλ‹€.

2. try-catch문을 톡해 InterruptedException λ°œμƒμ„ μž‘μ•„λ‚΄μ–΄ try λ¬Έμ—μ„œ μ‹€ν–‰ν•˜λ˜ κ²ƒμ—μ„œ λΉ μ Έλ‚˜μ˜¨λ‹€.

public class InterruptExample extends Thread {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // μŠ€λ ˆλ“œμ˜ μž‘μ—… μˆ˜ν–‰
                System.out.println("Running...");
                Thread.sleep(1000);  // μŠ€λ ˆλ“œκ°€ μž μ‹œ 멈좀
            } catch (InterruptedException e) {
                // μΈν„°λŸ½νŠΈκ°€ λ°œμƒν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•˜κ³  μŠ€λ ˆλ“œλŠ” 깨어남
                System.out.println("Thread interrupted, stopping...");
                break; // 루프λ₯Ό λΉ μ Έλ‚˜κ°μœΌλ‘œμ¨ μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œ
            }
        }
        // ν•„μš”ν•œ 정리 μž‘μ—… μˆ˜ν–‰
        System.out.println("Thread exiting...");
    }

    public static void main(String[] args) {
        InterruptExample thread = new InterruptExample();
        thread.start();

        try {
            Thread.sleep(3000);  // 메인 μŠ€λ ˆλ“œ λŒ€κΈ°
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread.interrupt();  // μŠ€λ ˆλ“œμ— μΈν„°λŸ½νŠΈ μš”μ²­
    }
}