JAVA/자바의 정석

[자바의 정석 - 기초편] 13. (2) sleep() / interrupt() / suspend() / resume() / join() / yield() / 쓰레드의 동기 / wait() / notify()

서영22 2023. 12. 21. 02:54

 sleep() 

- 현재 쓰레드를 지정된 시간동안 멈추게 함

static void sleep(long millis)                     // 천분의 일초 단위
static void sleep(long millis, int nanos)    // 천분의 일초 + 나노초

 

 

- 예외처리를 해야함 (InterruptedException이 발생하면 깨어남)

 

 

 

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

 

 

 

 interrupt() 

- 대기상태(WAITING)인 쓰레드를 실행대기 상태(RUNNABLE)로 만듦

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

 

 

 

 

 suspend() / resume() / stop() 

- 쓰레드의 실행을 일시정지, 재개, 완전 정지 시킴

- 교착상태(dead-lock)에 빠지기 쉬워서 deprecated 됨 (사용 권장 X)

 

void suspend()    쓰레드를 일시정지 시킨다
void resume()      suspend()에 의해 일시정지된 쓰레드를 실행대기상태로 만든다
void stop()           쓰레드를 즉시 종료시킨다

 

 

 

 

 

 join() 

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

void join()                                    // 작업이 모두 끝날 때까지
void join(long millis)                    // 천분의 일초 동안
void join(long millis, int nanos  // 천분의 일초 + 나노초 동안

 

 

- 예외처리 해야 함 (InterruptedException이 발생하면 작업 재개)

 

 

 

< 예제 >

 

 

 

 yield() 

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

 

- static메서드라서 자기자신만 가능

 

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

 

 

 

 쓰레드의 동기화 (synchronization) 

쓰레드의 동기화 : 한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것

 

- 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있음

 

- 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 동기화 필요

 

- 동기화를 하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정

 

- 임계 영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입 가능 (객체 1개에 락 1개)

 

 

 

 synchronized를 이용한 동기화 

synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지

1. 메서드 전체를 임계 영역으로 지정
2. 특정한 영역을 임계 영역으로 지정

 

 

 

< 예제 >

 

- 동기화 안했을 때 ➔ 잔고가 음수로 떨어질 수 있음

 

 

 

- 동기화 하면 음수로 안떨어짐

 

 

 

 

 wait() / notify() 

- 동기화의 효율을 높이기 위해 사용

 

- Object클래스에 정의되어 있으며 동기화 블록 내에서만 사용할 수 있음

 

wait()         객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣음
notify()       waiting pool에서 대기중인 쓰레드 중의 하나를 깨움
notifyAll()   waiting pool에서 대기중인 모든 쓰레드를 깨움

 

 

 

< 예제 >

 

- 요리사 = Table에 음식 추가  / 손님 = Table의 음식 소비

- 요리사와 손님이 같은 객체(Table)을 공유하므로 동기화 필요

 

 

➔ 요리사는 테이블이 가득 차면 대기(wai)하고, 음식을 추가하고나면 손님에게 통보(notify())함

➔ 손님은 음식이 없으면 대기(wait())하고, 음식을 먹고나면 요리사에게 통보(notify())함