1 쓰레드의 상태 싸이클
- New 상태 : "new MyThread();"한 상태, 아직은 JVM은 이를 'Thread'라고 생각하지 않음.
- Runnable 상태 : "start();" 한 상태와 Waiting 상태에서 (ex. interrupt(),notify(),notifyall() 해줬을 때
이제 JVM은 이를 'Thread'라고 생각함.
JVM의 '쓰레드 스케줄러'에 의해서 선택될 수 있는 상태. - Running 상태 : "run();" 가 실행되고 있는 상태.
- Blocked 상태 : Waiting 상태라고도 한다. (ex. sleep(), join() wait() 등) 쓰레드가 잠시 정지된 상태
- Dead 상태 : Thread 실행에 필요한 관련 정보들이 메모리로부터 소멸되어 사라진 상태.
쓰레드가 종료된 상태를 말한다.
이 때 다른 쓰레드에게 자원을 양보하여 다른 쓰레드가 좀더 빨리 끝날수있도록 한다.
(또다시 Runnable로 갈 수 없음.)
2 쓰레드의 상태 제어 메서드
1. join()
join() 메서드는 해당 메서드가 처리될 때 까지 main() 쓰레드가 실행되지 못하게 정지 시켜둔다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package Thread;
class JoinThread extends Thread{
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("MyThread"+(i+1));
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MyThread_Join {
public static void main(String[] args) {
JoinThread th = new JoinThread();
th.start();
System.out.println("시작");
// try {
// th.join();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("종료!");
}
}
|
cs |
Thread 객체를 상속받는 JoinThread 클래스를 만들어 쓰레드 객체를 생성하였다.
run() 메서드를 오버라이딩하여 MyThread 를 5번 출력받고 sleep() 으로 0.5 초동안 출력하게 하도록 설정하였다.
그리고 메인 메서드에 줄20과 28 과 같이 작성 후 쓰레드 객체 생성, start() 호출해준다. 그리고 실행하면 다음과 같이 출력된다.
그리고 위의 주석처리 부분을 해제하게 되면 join() 메서드가 th 쓰레드가 다 실행될 때까지 main 쓰레드를 Blocked시키기고 th가 끝나고 나서 실행하기 때문에 다음과 같이 출력된다.
2. wait(), notify()
해당 메서드들은 동기화된 블럭 안에서 사용해야 한다.
모니터링 락을 들고 있다가도 wait()를 사용하면 모니터링 락을 다른 쓰레드에게 넘기고 대기하게 되고 notify() 를 통해 해당 대기에서 빠져나오게 된다.
쓰레드를 생성할 때 wait()를 기다릴 쓰레드에, notify()를 다른 쓰레드에서 wait()를 쓴 쓰레드를 깨워줄 타이밍에 사용해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package Thread;
class ThreadNotify extends Thread {
int total; // 누적할 수 있는 변수 선언
public void run() { // 메서드 오버라이딩
synchronized (this) { // 해당부분은 동기화 되고 있어야함 (동기화 블럭생성)
for (int i = 0; i < 5; i++) {
System.out.println((i+1)+"을 더합니다.");
total += 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify(); // synchronized() 안에 작성
}
}
}
public class ThreadWait {
public static void main(String[] args) {
ThreadNotify b = new ThreadNotify();
b.start(); // 모니터링 락을 획득
synchronized (b) { // 메인 쓰레드
try {
System.out.println("b가 완료될때까지 기다립니다.");
b.wait(); // InterruptedException 처리 해야함.
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Total is : "+b.total);
}
}
}
|
cs |
줄3에서 쓰레드를 상속받는 쓰레드 객체를 생성하고 줄4에서 누적할 수 있는 변수 total 을 선언한다.
그리고 run() 메서드를 오버라이딩하고 줄6에서 synchronized 를 통해 동기화 시켜준다. 매개변수로는 객체 자신을 넣었다. (this) 동기화는 notify() 를 사용해야 하기 때문에 해주었다.
그리고 for 문으로 실행내용을 5번동안 sleep()으로 0.5 간 반복해주었다. 반복이 끝나면 for문을 빠져나오고 notify() 를 만나 main애서 wait() 걸어줄 메인 쓰레드을 Runnable 하게 설정했다. (notify() 동기화 구문 안에 작성해야함.)
그리고 main() 메서드에서 객체의 생성과 동시에 start() 를 호출하여 main()에서 모니터링 락을 획득(=Runnable)하였으며 메인 메서드 안에 synchronized 하여 참조변수를 notify() 해야할 객체 b로 담고 먼저 줄27을 실행하고 나서 메인 메서드가 Blocked 될 수 있게 wait() 처리 하였다. 그리고 wait() 가 예외처리를 해줘야 하기 때문에 위처럼 try catch 로 예외처리를 해주었고, b 쓰레드가 끝나고 나면 끝났다고 알려줄 수 있게 줄32에서 total값을 출력하였다.
'Java > Java 기초문법' 카테고리의 다른 글
[JAVA 기초] 쓰레드(Thread) 3 - 동기화(Synchronized)와 데몬쓰레드(Daemon Thread) (0) | 2021.04.13 |
---|---|
[JAVA 기초] 쓰레드(Thread) 2 - 쓰레드 생성방법2 와 쓰레드 우선순위(setPriority) (0) | 2021.04.12 |
[JAVA 기초] 쓰레드(Thread) 1 - 쓰레드 생성방법1 (0) | 2021.04.12 |
[JAVA 기초] 자바 예외처리 3 - 사용자 정의 예외(user-defined exception) 와 예외처리 연습문제 (0) | 2021.04.12 |
[JAVA 기초] 자바 예외처리 2 - 예외의 종류(Checked, Unchecked)와 예외 발생(throws, throw) (0) | 2021.04.11 |
댓글