자바 스터디

[자바의 정석] CH13.8 쓰레드의 실행제어

changha. 2023. 7. 30. 18:29

20. 쓰레드의 상태

- NEW : 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태 

- RUNNABLE : 실행 중 또는 실행 가능한 상태

- BLOCKED : 동기화블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)

- WATING, TIMED_WATING : 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지상태, TIMED_WATING은 일시정지시간이 지정된 경우를 의미

- TERMINATED : 쓰레드의 작업이 종료된 상태 

 

21. 쓰레드의 실행제어 

쓰레드의 실행을 제어할 수 있는 메서드가 제공된다. 

 

static 메서드 2개는 자기자신에게만 가능하다. 남을 재울 수 없고 자기를 재울 수 있다고 예시 들어줌

22. sleep()

현재 쓰레드를 지정된 시간동안 멈추게 한다.

static void sleep(long millis)

예외처리를 해야 한다. (InterruptedException이 발생하면 깨어남)

try{
	Thread.sleep(1, 500000);
} catch (InterruptedException e) {}

특정 쓰레드를 지정해서 멈추게 하는 것은 불가능하다. 

try{
	th1.sleep(2000);
} catch (InterruptedException e) {}

->

try {
	Thread.sleep(2000);
} catch (InterruptedException e) {}

th1처럼 특정 쓰레드를 지정해도 에러는 안나지만 자기 자신만 sleep만 가능함 

그래서 클래스이름을 쓰는것이 좋다. 

 

23. interrupted()

대기상태(WAITING)인 쓰레드를 실행대기 상태(RUNNABLE)로 만든다.

 void interrupt() // 쓰레드 intrrupted상태를 false에서 true로 변경.
 void isInterrupted() // 쓰레드 interrupted상태를 반환.
 static boolean interrupted() // 현재 쓰레드의 interrupted상태를 알려주고, false로 초기화

 

쓰레드의 상태를 변경 시키고 싶을 때 (ex, 다운로드 취소, 다운로드 대기를 실행으로 변경)

class ThreadEx13_2 extends Thread {
	public void run() {
    	...
        while (download && !isInterrupted()){
			// download를 수행한다.
            ...
		}
        System.out.println("다운로드가 끝났습니다.");
    }
}

 

24~26. suspend(), resune(), stop()

suspend() : 실행상태에서 일시정지로 이동 

resume() : 일시정지에서 줄서는 상태(실행대기)로 이동 

 

사용하면 편리하지만 현재 deprecated됨, dead-lock 교착상태에 빠지기 쉬워서 

 

27. join()

지정된 시간동안 특정 쓰레드가 작업하는 것을 기다린다.

 

메모리 부족하면 intterupt()-> 메모리를 사용한다. 

하지만 위 로직에서 빠진것이 있다

바로 gc가 실행할 시간을 주도록 join을 넣어야 한다.

 

 

28. yield()

- 남은 시간을 다음 쓰레드에게 양보하고, 자신(현재 쓰레드)은 실행대기한다.

 

yield도 static 메서드라 자기자신만 가능 

... 
boolean suspended = false;
boolean stopped = false;

public void run() {
	while(!stoped){
    	if(!suspended){
        	
            try{
            	Thread.sleep(1000);
            } catch(InterruptedException e) {}
        } else {
        	Thread.yield();
        } // if 
    } // while 
}

 

-yield()와 interrupted()를 적절히 사용하면, 응답성과 효율을 높일 수 있다.

public void suspend() {
	suspended = true;
    th.interrupt();
}

interrupt를 해야 sleep하는 시간을 interruptedException으로 빼서 딜레이 없이 정지가 가능하다.