YOUNGJIN

자바의 정석 13장 ( Thread ) 본문

Study/Java

자바의 정석 13장 ( Thread )

Youngjin Noh 2023. 1. 18. 17:59

쓰레드

쓰레드를 구현하는 방법은 Thread클래스를 상속받는 방법과 Runnable인터페이스를 구현하는 방법, 모두 두 가지가 있다. 어느 쪽을 선택해도 별 차이는 없지만 Thread클래스를 상속받으면 다른 클래스를 상속받을 수 없기 때문에, Runnable인터페이스를 구현하는 방법이 일반적이다.

class ThreadEx1{
    public static void main(String args[]){
        ThreadA t1=new ThreadA();
        Thread t2=new Thread(new ThreadB());
        
        t1.start();
        t2.start();
    }
}

class ThreadA extends Thread{
    public void run(){
    	for(int i=0;i<5;i++)
        	System.out.println(getName());
    }
}

class ThreadB implements Runnable{
    public void run(){
    	for(int i=0;i<5;i++)
        	System.out.println(Thread.currentThread().getName());
    }
}

 

데몬쓰레드

데몬쓰레드는 일반쓰레드의 작업을 돕는 보조적인 역할을 수행하는 쓰레드이다. 일반쓰레드가 모두 종료되면 데몬쓰레드는 강제적으로 자동 종료된다. 데몬쓰레드는 일반쓰레드의 작성방법과 실행방법이 같으며 다만 쓰레드를 생성한 다음 실행하기 전에 setDemon(true)를 호출하기만 하면 된다.

Thread t=new Thread(new ThreadEx());
t.setDaemon(true);
t.start();

 

쓰레드의 실행제어

 

쓰레드의 동기화

한 쓰레드가 특정 작업을 끝마치기 전까지 다른 쓰레드에 의해 방해받지 않도록 하는 임계영역을 도입하기 위해 synchronized 키워드를 이용한다.

//방법1
public synchronized void withdraw(int money){
    if(balance>=money){
    	try{Thread.sleep(1000);}catch(Exception e){}
        balance-=money;
    }
}

//방법2
public synchronized void withdraw(int money){
    synchronized(this){
	if(balance>=money){
    		try{Thread.sleep(1000);}catch(Exception e){}
        	balance-=money;
    	}
    }
}

 

wait()와 notify()

synchronized로 동기화해서 공유 데이터를 보호하는 것 까지는 좋은데, 특정 쓰레드가 객체의 락을 가진 상태로 오랜 시간을 보내지 않도록 하기 위해 wait()과 notify()를 이용한다.

wait()과 notify()는 Object클래스에 정의되어있다.

void wait()

void wait(long timeout)

void notify()

 

그 외에 쓰레드 관련 개념

Lock & Condition: 메서드 내에서만 lock을 걸 수 있다는 synchronized 문법의 단점을 보완하기 위해 추가된 동기화 방법

 

volatile: 보통 컴퓨터는 메모리에서 읽어온 값을 캐시에 저장하고 캐시에서 값을 읽어서 작업하는데, 멀티코어 프로세서를 이용할 경우 메모리에 저장된 변수가 다른 쓰레드에 의해 변경되었음에도 불구하고 캐시에 있는 변수 값은 변경되지 않을 수 있다. 이런 상황에서 변수 앞에 volatile을 붙이면, 캐시가 아닌 메모리에서 값을 직접 읽어온다.

volatile boolean stopped = false;

 

fork & join: 하나의 작업을 작은 단위로 나눠서 여러 쓰레드가 동시에 처리하는 것을 쉽게 만들기 위해 이용. RecursiveAction과 RecursiveTask 두 클래스 중 하나를 상속받아 구현

 

Comments