쓰레드
프로그램 vs 프로세스
프로그램은 실행 가능한 파일 (.exe)이고 프로세스는 실행 중인 프로그램이다.
하나의 프로그램에 여러 개의 프로세스가 가능하다.
예를 들어, 한글 프로그램이 하나 깔려있으면 우리는 한글 프로그램을 1개 이상 띄워서 사용할 수 있다.
프로세스 vs 쓰레드
쓰레드는 프로세스 안에서 실제 작업을 수행한다. 프로세스를 공장이라고 치면 쓰레드는 일꾼인 것이다. 그렇기 때문에 프로세스 안에 여러 개의 쓰레드가 가능하다.
하나의 프로세스에서 여러 개의 쓰레드가 실행되는 것을 멀티쓰레드(딩)이라 한다.
멀티쓰레드의 장점
- 자원을 효율적이게 사용할 수 있음.
- 사용자에 대한 응답성이 향상
- 코드가 간결
우리가 카카오톡을 사용할 때 사진을 보내고 채팅을 할 수 있는 것은 멀티쓰레드를 사용하기 때문이다. 만약 싱글 쓰레드를 사용한다면, 우리가 사진을 전송하고 그 사진이 전송이 완료될 떄까지 채팅을 할 수 없다.
멀티쓰레드의 단점
- 동기화 주의
- dead lock 발생 가능
- 쓰레드들이 효율적으로 사용하도록 우선순위를 잘 정해야함
쓰레드 객체
쓰레드 객체를 생성하는 두 가지 방법이 있다.
- Thread 클래스 상속받기
Thread 클래스의 run 메소드를 오버라이딩한다.
1
2
3
class A extends Thread{
public void run(){}
}
- Runnable 인터페이스 구현하기
Runnable 인터페이스의 run 추상메소드를 구현한다.
1
2
3
class B implements Runnable{
public void run(){}
}
쓰레드 인스턴스
쓰레드 인스턴스는 다음과 같이 사용된다.
1
2
3
4
5
6
A a = new A(); // Thread 상속받은 클래스 A
a.start();
B b = new B(); // Runnable 구현한 클래스 B
Thread tb = new Thread(b);
tb.start();
start로 Thread를 실행시키면 별도의 메모리공간이 생기고 오버라이딩하거나 구현한 run 메소드가 실행된다.
데몬쓰레드
데몬쓰레드는 보조 쓰레드로 일반 쓰레드가 종료되면 자동적으로 종료된다. 대표적인 예로는 가비지 컬렉터가 있다. 데몬쓰레드는 start를 호출 전에 setDaemon(True)
을 선언하지 않으면 IlleagalThreadStateException
이 발생한다.
쓰레드 상태
New | start()호출 전 쓰레드 인스턴스 생성 |
Runnable | start()호출 후 실행 중이거나 대기줄에 있는 상태 |
Waiting | 일시정지 상태 |
Blocked | 동기화 블럭으로 인해 일시정지 상태 |
Terminated | 실행 종료 상태 |
sleep
static메소드이고 다른 쓰레드에는 사용할 수 없다. 호출 시 실행중인 쓰레드의 상태를 waiting으로 바꾸고 설정한 시간이 지나면 자동적으로 runnable상태로 바꾼다. 예외처리(InterruptedException
) 해줘야한다.
1
2
3
try{
Thread.sleep(1000)// 1초 일시정지후 다시 실행됨
}catch(InterruptedException e){} // 예외 발생시 깨어남
yield
static메소드이고 다른 쓰레드에는 사용할 수 없다. 실행 중지하고 실행대기줄로 간다.(계속 runnable상태)
interrupt
waiting상태의 쓰레드를 runnable상태로 바꾼다.
join
지정된 시간동안 해당 쓰레드가 끝나기를 기다린다.예외처리(InterruptedException
) 해줘야한다.
1
2
3
4
5
6
7
8
9
10
Thread t1 = new Thread();
Thread t2 = new Thread();
t1.start();
t2.start();
try{
t1.join(); // 현재 쓰레드는 th1 쓰레드가 종료될 때까지 기다림
t2.join(10000); // 현재 쓰레드는 th2 쓰레드가 10초동안 작업 진행 하는 것을 기다림
}catch(InterruptedException e){}
suspend, stop, resume
일시중지, 완전정지, 재개 시키는데 교착상태(dead lock상태)에 빠질 수 있어 사용권장X
동기화
동기화는 하나의 객체에 하나의 쓰레드만 접근할 수 있도록 하여 데이터의 일관성을 유지한다.
메서드 선언부의 리턴타입 앞에 synchronized를 붙이거나 동기화 블럭을 사용하여 동기화를 할 수 있다.
1
2
3
4
5
6
7
synchronized(객체의 참조변수){
}
public synchronized void method(){
}
wait, notify
동기화의 효율성을 위해 wait, notify, notifyAll 메소드를 사용한다.
wait() 호출 시 하나의 객체에서 실행중인 쓰레드가 빠져나가 객체의 waiting pool로 가고 다른 쓰레드가 객체에 접근할 수 있도록 한다.
notify() 호출 시 객체의 waiting pool에 있는 랜덤으로 하나의 쓰레드를 깨운다. notifyAll() 호출 시 객체의 waiting pool에 있는 모든 쓰레드를 깨운다. (객체 접근은 랜덤적으로 하나만 가능)
Comments powered by Disqus.