상태제어
- 실행중인 스레드의 상태를 변경하는 것을 말한다.
- 상태변화를 가져오는 메소드의 종류
※ 주어진 시간동안 일시정지 - sleep()
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
- 얼마동안 일시 정지 상태로 있을 것인지, 밀리세컨드(1/1000초) 단위로 지정
- 일시정지 상태에서 interrupt() 메소드가 호출되면 InterruptedException 발생
예제:
package threadsleep;
import java.awt.*;
public class SleepExample {
public static void main(String[] args) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for (int i = 0; i < 10; i++) {
toolkit.beep();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
}
}
※ 다른 스레드에게 실행 양보 - yield()
package threadyield;
public class YieldExample {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();
threadA.start();
threadB.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
threadA.work = false; // 3초 후 threadB만 계속 출력
}
}
package threadyield;
public class ThreadA extends Thread {
public boolean stop = false;
public boolean work = true;
@Override
public void run() {
while (!stop) {
if (work) {
System.out.println("ThreadA 작업내용");
} else {
Thread.yield();
}
}
System.out.println("ThreadA 종료");
}
}
package threadyield;
public class ThreadB extends Thread {
public boolean stop = false;
public boolean work = true;
@Override
public void run() {
while (!stop) {
if (work) {
System.out.println("ThreadB 작업내용");
} else {
Thread.yield();
}
}
System.out.println("ThreadB 종료");
}
}
메인메소드의 다음과 같은 코드로 스레드를 종료할수 있다.
// threadA.stop(); -- deprecated
threadA.stop = true;
threadB.stop = true;
※ 다른 스레드의 종료를 기다림 - join()
- 계산작업을 하는 스레드가 모든 계산 작업을 마쳤을 때, 계산 결과값을 받아 이용하는 경우에 주로 사용
join 적용전 예제:
package threadjoin;
public class SumThread extends Thread {
private long sum;
public long getSum() {
return sum;
}
public void setSum(long sum) {
this.sum = sum;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
sum += i;
}
}
}
package threadjoin;
public class JoinExample {
public static void main(String[] args) {
SumThread sumThread = new SumThread();
sumThread.start();
System.out.println("1~100 합 : " + sumThread.getSum());
}
}
결과:
1~100 합 : 0
join 적용
package threadjoin;
public class JoinExample {
public static void main(String[] args) {
SumThread sumThread = new SumThread();
sumThread.start();
try {
sumThread.join();
} catch (InterruptedException e) {
}
System.out.println("1~100 합 : " + sumThread.getSum());
}
}
결과:
1~100 합 : 5050
※ 스레드간 협업 - wait(), notify(), notifyAll()
- 동기화 메소드 또는 블록에서만 호출 가능한 Object의 메소드
- wait():
호출한 스레드 일시정지
다른 스레드가 notify() 또는 notifyAll()을 호출하면 실행대기 상태가 된다.
wait(long timeout), wait(long timeout, int nanos)
notify()가 호출되지 않아도 시간이 지나면 스레드가 자동적으로 실행 대기 상태가 된다.
- 두 개의 스레드가 교대로 번갈아 가며 실행해야 할 겨우에 주로 사용
예제:
package ex04_wait_notify;
public class WaitNotifyExample {
public static void main(String[] args) {
WorkObject sharedObject = new WorkObject();
ThreadA threadA = new ThreadA(sharedObject);
ThreadB threadB = new ThreadB(sharedObject);
threadA.start();
threadB.start();
}
}
package ex04_wait_notify;
public class WorkObject {
public void methodA() {
System.out.println("ThreadA의 methodA() 작업 실행");
}
public void methodB() {
System.out.println("ThreadB의 methodB() 작업 실행");
}
}
package ex04_wait_notify;
public class ThreadA extends Thread {
private WorkObject workObject;
public ThreadA(WorkObject workObject) {
this.workObject = workObject;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
workObject.methodA();
}
}
}
package ex04_wait_notify;
public class ThreadB extends Thread {
private WorkObject workObject;
public ThreadB(WorkObject workObject) {
this.workObject = workObject;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
workObject.methodB();
}
}
}
결과:
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadB의 methodB() 작업 실행
작업 A,B가 번갈아 가며 실행되지 못함.
수정한 WorkObject 객체:
package ex04_wait_notify;
public class WorkObject {
public synchronized void methodA() {
System.out.println("ThreadA의 methodA() 작업 실행");
notify();
try {
wait();
} catch (InterruptedException e) {
}
}
public synchronized void methodB() {
System.out.println("ThreadB의 methodB() 작업 실행");
notify();
try {
wait();
} catch (InterruptedException e) {
}
}
}
실행결과:
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
ThreadA의 methodA() 작업 실행
ThreadB의 methodB() 작업 실행
'자바' 카테고리의 다른 글
[스레드] 8. 데몬 스레드 (0) | 2022.05.01 |
---|---|
[스레드] 7. 스레드 상태제어 (0) | 2022.04.24 |
[스레드] 5. 스레드 상태 (0) | 2022.04.24 |
[스레드] 4. 동기화 메소드와 동기화 블록 (0) | 2022.04.24 |
[스레드] 3. 스레드 우선 순위 (0) | 2021.12.29 |