일반쓰레드 <-> 데몬쓰레드(보조쓰레드)
void join() // 작업이 모두 끝날 때까지
void join(long millis) // 천분의 일초 동안
void join(long millis, int nanos) // 천분의 일초 + 나노초 동안
public static void main(String args[]){
ThreadEx19_1 th1 = new ThreadEx19_1();
ThreadEx19_2 th2 = new ThreadEx19_2();
th1.start();
th2.start();
startTime = System.currentTimeMillis();
try{
th1.join(); // main쓰레드가 th1의 작업이 끝날 때까지 기다린다.
th2.join(); // main쓰레드가 th2의 작업이 끝날 때까지 기다린다.
}catch(InterruptedException e) {}
System.out.print("소요시간:" + (System.currentTimeMillis()
- ThreadEx19.startTime));
} // main
public void run(){
// 일반 쓰레드
while(true){
try{
Thread.sleep(10 * 1000); // 10초 기다린다.
}catch(InterruptedException e){
System.out.println("Awaken by interrupt().");
}
gc(); // garbage collector 수행
System.out.println("Garbage Collected. Free Memory :" + freeMemory());
}
}
garbage collector
public void gc(){
for(int i = 0; i < 20; i++){
requireMemory = (int)(Math.random() * 10) * 20;
// 필요한 메모리가 사용할 수 있는 양보다 적거나
// 전체 메모리의 60%이상 사용했을 경우 gc를 깨운다.
if(gc.freeMemory() < requiredMemory ||
gc.freeMemory() < gc.totalMemory() * 0.4)
{
gc.interrupt(); // 잠자고 있는 쓰레드 gc를 깨운다.
// join()필요
// gc가 작업할 시간을 줘야한다!!
// 깨우기만하고 메모리 쓸 수 없음.
try{
gc.join(100);
}catch(InterruptedException e) {}
}
gc.usedMemory += requireMemory; // 메모리 사용
System.out.println("usedMemory:"+gc.usedMemory);
}
}
남은 시간을 다음 쓰레드에게 양보하고, 자신(현재 쓰레드)은 실행대기한다.
yield()와 interrupt()를 적절히 사용하면, 응답성과 효율을 높일 수 있다.
class MyThreadEx18 implements Runnable{
boolean suspended = false;
boolean stopped = false;
Thread th;
MyThreadEx18(String name){
th = new Thread(this, name);
}
public void run(){
while(!stopped){
if(!suspended){
/*
작업수행
*/
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
} else{
Thread.yield();
// else문의 yield가 없다면 while문이 계속 돌아 busy waiting 상태가 될 수 있음.
// 그러느니 차라리 뒷사람에게 양보하는 것이 좋다.
}
} // while
}
}
public void start(){
th.start();
}
public void resume(){
suspended = false;
}
public void suspend(){
suspended = true;
// sleep으로 인해 자고있을 확률이 있으므로 빨리 벗어나기 위해 interrupt를 넣는다.
// 응답성 향상
th.interrupt();
}
public void stop(){
stopped = true;
// sleep으로 인해 자고있을 확률이 있으므로 빨리 벗어나기 위해 interrupt를 넣는다.
// 응답성 향상
th.interrupt();
}
yield는 OS스케쥴러에게 양보해달라고 통보하는 것이다. yield를 사용한다고 원하는 값을 기대하기 쉽지 않다. yield 사용유무는 결과에 큰 차이를 주지 않는다.