13-28~29 join(), yield()

oyeon·2021년 3월 19일
0

Java 개념

목록 보기
57/70

일반쓰레드 <-> 데몬쓰레드(보조쓰레드)

join()

  • 지정된 시간동안 특정 쓰레드가 작업하는 것을 기다린다.
void join()				// 작업이 모두 끝날 때까지
void join(long millis)			// 천분의 일초 동안
void join(long millis, int nanos)	// 천분의 일초 + 나노초 동안
  • 예외처리를 해야 한다.(InterruptedException이 발생하면 작업 재개)
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

Case

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()

  • 남은 시간을 다음 쓰레드에게 양보하고, 자신(현재 쓰레드)은 실행대기한다.

  • 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 사용유무는 결과에 큰 차이를 주지 않는다.

profile
Enjoy to study

0개의 댓글