(오키) 자바의정석, 챕터 13 - 쓰레드

쓰레드 구현과 실행

1.Thread 클래스 상속

1
2
3
4
5
6
7
8
9
10
class MyThread extends Thread {
public void run() { // run을 오버라이딩

// 작업 내용
// this.getName();
}
}

MyThread t1 = new MyThread();
t1.start();

2.Runnable 인터페이스 구현

1
2
3
4
5
6
7
8
9
10
11
12
class myThread2 implements Runnable {
public void run() { // 인터페이스 추상 메서드 run 구현

// 작업 내용
//Thread.currentThread().getName();
}
}

Runnable r = new MyThread2();
Thread t2 = new Thread(r); // Thread(Runnable r)
// Thread t2 = new Thread(new MyThread2());
t2.start();

쓰레드가 종료 될때까지 기달리는 함수 join();

1
2
t1.join();
t2.join();

쓰레드의 I/O 블락킹 (blocking)

쓰레드의 우선순위 함수 setPriority (int newPriority);
인자로 쓰는 상수
MAX_PRIORITY = 10; // 최대
NORM_PRIORITY = 5; //보통
MIN_PRIOIRTY = 1; // 최소

쓰레드 그룹, 지정하지 않으면 main 쓰레드 그룹에 속하게 되고 자신이 상속한 부모의 우선순위를 따라간다. (5)

13-18 데모 쓰레드 (deamon thread)

일반 쓰레드의 작업을 돕는 보조적인 역할 수행
일반 쓰레드가 종류 되면 자동으로 종료

사용 처: 가비지 컬렉터, 자동저장, 화면 자동 갱신 등

일반 적인 구현 예: 무한루프에 조건문 확인 하여 특정 일을 처리 이후 대기

1
2
3
4
5
6
7
8
9
10
11
12
13
public void run() {
while(true) {
try {
Thread.sleep(3*1000); // 3초마다 대기
}
if(autoSave) { // 조건문 확인
autoSave(); // 일 처리
}
}
}
Thread t = new Thread(new)
setDaemon(boolean on); // 설정
isDeamon() ; 데몬 쓰레드 인지 확인

13-20 쓰레드의 상태

생성 만 된 상태 (start() 호출 전): NEW
실행 혹은 실행 가능한 상태 (줄서있는 상태): RUNNABLE
동기화 블럭에 위해 일시정된 상태(LOCK 풀릴때까지): BLOCKED
일시정지 상태:WAITING, TIMED_WAITING
종료: TERMINATED

suspend(); // 일시 정지

sleep(long mills); // 잠자기
wait(); join(); // 기다리기

I/O block; // 입출력 대기 상태
interrupt(); // 깨우는 것
stop();
resume();
yield();

sleep()

exception 이 필수로 나와서 try catch 로 싸야 한다.
util 함수를 하나 만들어 쓰면 간편

interrupt()

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

1
2
3
4
5
6
7
8
class ThreadEx extends Thread {
public void run() {
//...
while( downloaded && !isInterrupted()) {
// download 완료 혹은 취소
}
}
}

suspend(), resume(), stop()

dead-lock 교착 상태 발생 빈번이 되어서 현재 deprecated 되었음 > 사용 권장 X
유사 기능이 필요할때는 멤버 변수를 활용 해서 유저 레벨 에서 구현 하면 된다.

join()

th1.join(); // th1이 종료 할때까지 기달린다.
try - catch 로 묶고 Interrupted Exception로 나올수도 있다.

yield()

yield()와 interrupt()을 적절히 사용 하면 응답성과 효율을 높힌다.
sleep() 으로 길게 돌고 있을때 busy-wait 가 될수 있다.

그래서 interrupt 로 빨리 깨워서 동작 시키거나
sleep() 하는 대신 yield() 호출 해서 효율을 높힌다.

동기화 synchronization

  • 멀티 쓰레드, 서로 간섭이 없도록 ‘동기화’ 해준다

임계영역 : critical section
lock을 얻은 쓰레드 한개만 임계영역에 들어갈수 있다.

1.메세드 전체 임계 영역 지정

1
2
3
4
public synchronized void calcSum() {

//.. 전체를 critical section 으로 지정
}

2.특정 부분만 지정

1
2
3
synchronized(객체의 참조 변수) {
// ...
}

wait()와 notify()

동기화 효율을 높이기 위해 wait(), notify() 사용
Object 클래스에 정의 되어 있으며, 동기화 블록 내에서만 사용 할수 있다.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Account {
int balance = 1000;

public synchronized void withdraw(int money) {
while (balance < money) {
try {
wait(); // 대기 - 락을 풀고 대기 한다

} catch (interruptedException e) {}
}
balance -= money;
}

public synchronized void deposit(int money) {
balance += money;
notify(); // - 대기 중인 쓰레드 중 하나 에게 알림
}
}