[기본 개념] 8 | (1.3) 스레드 실행제어

728x90

[기본 개념] 8 | (1.3) 스레드 실행제어

1 프로세스와 쓰레드

2 쓰레드의 구현과 실행

3 start( )와 run( )

4 싱글쓰레드와 멀티쓰레드

5 쓰레드의 우선순위

6 쓰레드 그룹(thread group)

7 데몬 쓰레드(daemon thread)

8> 쓰레드의 실행제어

9 쓰레드의 동기화

    9.1 synchronized를 이용한 동기화

    9.2 wait( )와 notify( )

    9.3 Lock과 Condition을 이용한 동기화

    9.4 volatile

    9.5 fork & join 프레임웍

8. 쓰레드의 실행제어 (1)

 쓰레드의 상태에 대해 알아보자.

 

상태 설명
NEW 쓰레드가 생성되고 아직 start( )가 호출되지 않은 상태
RUNNABLE 실행 중 또는 실행 가능한 상태
BLOCKED 동기화블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)
WAITING,
TIMED_WAITING
쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지 상태.
TIMED_WAITING은 일시정지시간이 지정된 경우를 의미한다.
TERMINATED 쓰레드의 작업이 종료된 상태.

 


time-out, resume( ), notify( ), interrupt( )

                                  

●             


suspend( ), sleep( ), wait( ),
join( ), I/O block

 
 

 

   
 

  일시정지
(WAITING, BLOCKED)
   

   


start( )




⑥stop( )

생성
(NEW)

  실행대기
(RUNNABLE)
    실행   소멸
(TERMINATED)
 

       

 

   
 

 

③yield( )

 

   

 

① 쓰레드 생성 후 start( )호출 후 실행대기열에 저장. 먼저 실행대기열에 들어온 쓰레드 먼저 실행

② 실행 대기상태에 있다가 자신의 차례가 되면 실행상태

③ 주어진 실행시간이 다되거나 yield( )를 만나면 다시 실행 대기상태. 다음 쓰레드가 실행상태가 됨

④ 실행 중에 suspend( ), sleep( ), wait( ), join( ), I/O block에 의해 일시정지상태

⑤ time-out, notify( ), resume( ), interrupt( )에 의해 일시정지상태를 벗어나 실행 대기열에 저장

⑥ 실행을 마치거나 stop( )이 호출되면 소멸

 

sleep(long millis) - 일정시간 동안 쓰레드를 멈추게 한다.

 sleep( )은 지정된 시간동안 쓰레드를 멈추게 한다.

 

static void sleep(long millis)

static void sleep(long millis, int nanos)

 

 sleep( )에 의해 일시정지 상태가 된 쓰레드는 지정된 시간이 다 되거나 interrupt( )가 호출되면(InterruptedException발생), 잠에서 깨어나 실행 대기상태가 된다.

 

 따라서 sleep( )을 호출할 때는 try-catch문으로 예외처리를 해줘야 한다.

 

sleep( )은 호출한 쓰레드에 작동하는 것이 아니라 현재 실행중인 쓰레드에 대해 작동한다.

 

interrupt( )와 interrupted( ) - 쓰레드의 작업을 취소한다.

 진행 중인 쓰레드의 작업이 끝나기 전에 취소시켜야 할 때 사용한다.

 

 interrupt( )는 쓰레드에게 작업을 멈추라고 요청할 뿐 강제로 종료시키진 못한다. 단지 interrupted상태를 바꾸는 것이다.

 

 interrupted( )는 현재 실행 중인 쓰레드에 대해 interrupt( )가 호출되었는지 알려주며, interrupted상태를 false로 초기화한다. 호출되지 않았다면 false, 호출되었다면 true를 반환한다.

 

 isInterrupted( )도 호출한 쓰레드에 대해 interrupt( )가 호출되었는지 확인하는 데 사용하지만, interrupted상태를 false로 초기화하지 않는다.

 

void interrupt( )                                쓰레드의 interrupted상태를 false에서 true로 변경

boolean isInterrupted( )               쓰레드의 interrupted상태를 반환

static boolean interrupted( )      현재 쓰레드의 interrupted상태를 반환 후, false로 변경

 

예제/ThreadEx13.java

import javax.swing.JOptionPane;

public class ThreadEx13 {
    public static void main(String[] args) throws Exception {
        ThreadEx13_1 th1 = new ThreadEx13_1();
        th1.start();

        String input = JOptionPane.showInputDialog("아무값이나 입력하세요.");
        System.out.println("입력하신 값은 " + input + "입니다.");
        th1.interrupt();    // interrupt()를 호출하면, interrupted상태가 true가 된다.
        System.out.println("isInterrupted() : " + th1.isInterrupted()); // true
    }
}

class ThreadEx13_1 extends Thread {
    public void run() {
        int i = 10;

        while (i != 0 && !isInterrupted()) {
            System.out.println(i--);
            for (long x = 0; x < 2500000000L; x++); // 시간 지연
        }
        System.out.println("카운트가 종료되었습니다.");
    }
}
실행결과

10
9
8
7
6
입력하신 값은 sdfs입니다.
isInterrupted() : true
카운트가 종료되었습니다.

 

 사용자의 입력이 끝나자 interrupt( )에 의해 카운트다운이 중간에 멈췄다.

 

 그러나 시간 지연을 위해 사용했던 for문 대신 Thread.sleep(1000)으로 1초 지연하도록 변경하면 카운트가 종료되지 않으며 isInterrupted( )의 결과가 false로 나온다.

 

 sleep( )에 의해 쓰레드가 멈춰있을 때, interrupt( )를 호출하면 InterruptedException이 발생되고, interrupted상태는 false로 자동 초기화된다. 따라서 sleep( )을 사용해서 catch블럭에 interrupt( )를 추가로 넣어주면 카운트 다운이 중단된다.

 

 

 

 

 

 

출처 | Java의 정석 (남궁 성)

728x90