๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] Thread์˜ stop()๊ณผ interrupt()์˜ ๋น„๊ต

์ถœ์ฒ˜

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();  // ์Šค๋ ˆ๋“œ์— ์ธํ„ฐ๋ŸฝํŠธ ์š”์ฒญ
    }
}