Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 구현
- 코테
- 자바
- two pointers
- Class
- Stack
- array
- geometry
- Math
- Binary Search
- Tree
- Data Structure
- 파이썬
- database
- sorting
- Binary Tree
- Method
- SQL
- hash table
- greedy
- Number Theory
- bit manipulation
- Matrix
- java
- dynamic programming
- Counting
- 코딩테스트
- string
- implement
- simulation
Archives
- Today
- Total
코린이의 소소한 공부노트
데몬 쓰레드와 쓰레드의 실행제어, 상태 본문
[데몬 쓰레드]
boolean isDaemon()
// 쓰레드 그룹이 데몬 쓰레드 그룹이면 true를 반환한다.
void setDaemon(boolean on)
// 쓰레드를 데몬 쓰레드 또는 사용자 쓰레드로 변경한다. on을 true로 지정하면 데몬 쓰레드가 된다.
// setDaemon()은 반드시 start()를 호출하기 전에 실행되어야 한다.
// start() 후에는 데몬 쓰레드로 변경할 수 없기 때문이다.
// start() 전에 setDaemon()을 호출하면 IllegalThreadStateException이 발생한다.
1. 일반 쓰레드(non-daemon thread)의 작업을 돕는 보조적인 역할을 수행하는 쓰레드
2. 일반 쓰레드가 모두 종료되면 자동적으로 종료된다.
3. 가비지 컬렉터(garbage collector), 자동저장, 화면 자동갱신 등에 사용된다.
4. 무한루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.
// 데몬 쓰레드를 이용한 자동저장 예시
class DTEx implements Runnable {
static boolean autoSave = false;
public static void main(String[] args) { // main(일반) 쓰레드
Thread t = new Thread(new DTEx());
t.setDaemon(true); // 이 부분이 없으면 종료되지 않는다.
t.start();
for(int i=1; i <= 10; i++) {
try{
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.print(i + " ");
if(i==5) autoSave = true; // 5초 후부터 자동저장 시작
} // for
System.out.println("프로그램을 종료합니다.");
} // main()
public void run() { // 데몬 쓰레드
while(true) { // 무한루프지만 일반 쓰레드가 모두 종료되면 자동종료되기 때문에 괜찮다.
try {
Thread.sleep(3 * 1000);
} catch(InterruptedException e) {}
if(autoSave) autoSave(); // autoSave의 값이 true이면 3초마다 autoSave()를 호출한다.
}
}
public void autoSave() {
System.out.println("작업파일이 자동저장되었습니다.");
}
} // end of class
// 위 코드를 실행시킨 결과
1 2 3 4 5 작업파일이 자동저장되었습니다.
6 7 8 작업파일이 자동저장되었습니다.
9 10 프로그램을 종료합니다.
// t.setDaemon(true);가 없을 때의 실행 결과
1 2 3 4 5 작업파일이 자동저장되었습니다.
6 7 8 작업파일이 자동저장되었습니다.
9 10 프로그램을 종료합니다. // main은 종료되었지만
작업파일이 자동저장되었습니다.
작업파일이 자동저장되었습니다. // 데몬 쓰레드는 무한루프를 돌고 있다.
...
[쓰레드의 상태]
1. NEW
- 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태
2. RUNNABLE
- 실행 중 또는 실행 가능한 상태
3. BLOCKED
- 동기화 블록에 의해 일시 정지된 상태
- lock이 풀릴 때까지 기다림
4. WAITING, TIMED_WAITING
- 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지 상태
- TIMED_WAITING은 일시정지 시간이 지정된 경우
5. TERMINATED
- 쓰레드의 작업이 종료된 상태
[쓰레드의 메서드]
1. 잠자기, 다른 쓰레드 기다리기 <-> 깨우기, 방해하기
1) sleep()
static void sleep(long millis)
static void sleep(long millis, int nanos)
// 지정된 시간동안 쓰레드를 일시정지 시킨다.
// millis는 천 분의 일초 단위, nanos는 10^(-9)초 단위
// 지정된 시간이 지나면(time-out) 자동적으로 다시 실행대기 상태가 된다.
// interrupt()로 깨울 수 있기 때문에 예외 처리가 필수적이다.
// sleep()은 static 메서드이기 때문에 자기 자신에게만 호출할 수 있다.
// 예시
try{
Thread.sleep(1, 500000); // 쓰레드를 0.0015초 동안 멈추게 한다.
} catch(InterruptedException e) { } // Exception의 자손이므로 checked error
// 예외처리를 매번 하는 것이 다소 귀찮으므로 따로 메서드를 만들어놓기도 한다.
static void delay(long millis){
try{
Thread.sleep(millis);
} catch(InterruptedException e) { }
}
...
delay(1000);
2) join()
void join()
void join(long millis)
void join(long millis, int nanos)
// 지정된 시간동안 쓰레드가 실행되로록 한다.
// 지정된 시간이 지나거나 작업이 종료(시간지정 없을 때)되면
// join()을 호출한 쓰레드로 다시 돌아와 실행을 계속 한다.
// sleep()과 마찬가지로 예외처리가 필수다.
// 예시
ThreadEx t1 = new ThreadEx();
ThreadEx t2 = new ThreadEx();
t1.start();
t2.start();
try{
t1.join(); // main쓰레드가 t1의 작업이 종료될 때까지 기다린다.
t2.join(); // main쓰레드가 t2의 작업이 종료될 때까지 기다린다.
} catch(InterruptedException e) { } // e가 발생하면 기다림을 멈추고 main의 일을 재개한다.
3) interrupt()
void interrupt()
// sleep()이나 join()에 의해 일시정지 상태(WAITING)인 쓰레드를 실행대기 상태(RUNNABLE)로 만든다.
// 쓰레드의 interrupted 상태를 false에서 true로 전환한다.
// 해당 쓰레드에서는 InterruptedException이 발생함으로써 일시정지 상태를 벗어난다.
boolean isInterrupted()
// 쓰레드의 interrupted 상태를 반환한다.
static boolean interrupted()
// 현재 쓰레드의 interrupted 상태를 반환하고, false로 초기화한다.
// static 메서드이기 때문에 자기 자신에게만 쓸 수 있다.
// 예시
// main()
ThreadEx t1 = new ThreadEx();
t1.start();
t1.interrupt();
// ThreadEx의 run()
System.out.println(this.isInterrupted()); // true
System.out.println(this.isInterrupted()); // true
System.out.println(Thread.interrupted()); // true
System.out.println(Thread.interrupted()); // false
// isInterrupted()는 상태를 바꾸지 않기 때문에
// 다시 호출해도 true가 출력되지만
// static 메서드인 interrupted()는 쓰레드의 상태를 false로 초기화해서
// 다시 호출하면 false가 출력된다.
2. 일시정지 <-> 재개 // 종료 - 3개의 메서드는 deprecated: 교착상태(dead-lock) 발생 가능성 높음
void suspend()
// 쓰레드를 일시정지 시킨다.
void resume()
// suspend()에 의해 일시정지 상태에 있는 쓰레드를 실행대기 상태로 만든다.
void stop()
// 쓰레드를 즉시 종료시킨다.
// 어떻게 동작하는지 쉽게 구현해놓은 코드
// Thread를 구현해놓은 클래스 내부
boolean suspended = false;
boolean stooped = false;
public void suspend() { suspended = true; }
public void resume() { suspended = false; }
public void stop() { stopped = true; }
public void run(){
while(!stopped){ // stop()이 호출되지 않는 동안 계속 while문을 수행한다.
if(!suspended){ // suspend()가 호출되면 resume()가 호출되기 전까지 if문을 실행하지 않는다.
// 메서드 실행 내용
}
}
}
3. 다른 쓰레드에게 실행 양보하기
static void yield()
// 실행 중에 다른 쓰레드에게 양보하고 실행대기 상태가 된다.
// 남은 시간을 실행 대기 상태의 맨 앞 쓰레드에게 양보하고
// 자신은 실행 대기 상태의 가장 뒤로 간다.
// static 메서드이기 때문에 자기 자신에게만 호출할 수 있다.
// 예시 - 위에 있던 코드
public void run(){
while(!stopped){
if(!suspended){ // 일시정시 상태가 되면 while문만 계속 돌게 된다.(busy-waiting)
// 메서드 실행 내용
} else{
Thread.yield(); // 이를 방지하기 위해 else문에 yield()를 쓸 수 있다.
}
}
}
'Java' 카테고리의 다른 글
람다식의 정의와 작성 방법 (0) | 2022.12.28 |
---|---|
쓰레드의 동기화와 실행제어 (0) | 2022.12.09 |
쓰레드의 우선순위와 그룹 (0) | 2022.11.30 |
싱글쓰레드와 멀티쓰레드의 실행 (0) | 2022.11.30 |
쓰레드의 구현 방법과 실행 (0) | 2022.11.30 |