Part7 쓰레드
쓰레드란
동시에 여러가지 작업을 동시에 수행할 수 있게 하는것
- 동시에 여러가지 작업을 수행할 수 있다.
- 프로세스란 현재 실행되고 있는 프로그램을 말한다.
- 자바 프로그램은 JVM에 위해 실행된다. 이 JVM도 프로그램중에 하나이다.
- 운영체제 입장으로 보면 자바도 하나의 프로세스로 실행 하는 것이다.
- 워드프로세서가 하나의 프로세스라면, 하나의 프로세스 안에서도 여러개의 흐름이 동작할 수 있다. 이것은 Thread라고 말한다.
쓰레드 만들기
자바에서 Thread를 만드는 방법은 크게 Thread 클래스를 상속받는 방법과 Runnable 인터페이스를 구현하는 방법이 있다.
- Thread를 상속 받아서 쓰레드를 생성하는 방법
- java.lang.Thread 클래스를 상속받는다. 그리고 Thread가 가지고 있는 run() 메소드를 오버라이딩한다.
- 10번 반복하면서 str를 찍는다.
- Thread 클래스를 상속받은 MyThread1을 사용하는 클래스
- Thread를 상속 받았으므로 MyThread1은 Thread 이다.
- 쓰레드를 생성하고, Thread 클래스가 가지고 있는 start() 메소드를 호출 한다.
- Runnable 인터페이스를 구현해서 쓰레드를 만드는 방법
- Runnable 인터페이스가 가지고 있는 run() 메소드를 구현한다.
- Runnable 인터페이스를 구현한 MyYhread2 사용하는 방법
- MyThread2는 Thread를 상속받지 않았기 때문에 Thread가 아니다.
- Thread를 생성하고, 해당 생성자에 MyThread2를 넣어서 Thread를 생성한다.
- Thread 클래스가 가진 start() 메소드를 호출한다.
쓰레드와 공유객체
하나의 객체를 여러개의 Thread가 사용한다는 것을 의미
MusicBox 라는 클래스가 있다고 가정한다. 해당 클래스는 3개의 메소드를 가지고 있다. 각각의 메소드는 1초 이하의 시간동안 10번 반복하면서,
어떤 음악을 출력한다. 이러한 MusicBox를 사용하는 MusicPlayer를 3명 만들어 보겠다.
MusicPlayer 3명은 하나의 MusicBox를 사용할 것이다. 이 때 어떤 일이 발생하는지 살펴보겠다.
- MusicBox를 가지는 Thread 객체 MusicPlayer
- MusicBox와 MusicPlayer를 이용하는 MusicBoxExam1 클래스
동기화 메소드와 동기화 블록
- 고유객체가 가진 메소드를 동시에 호출 되지 않돚록 하는 방법
- 메소드 앞에 synchronized 를 붙힌다.
- 여러개의 Thread 들이 공유객체의 메소드를 사용할 때 메소드에 synchronized가 붙어 있을 경우 먼저 호출한 메소드가 객체의 사용권(Monitoring Lock)을 얻는다.
- 메소드 앞에 synchronized 를 붙혀서 실행해 보면, 메소드 하나가 모두 실행된 후에 다음 메소드가 실행된다.
- 해당 모니터링 락은 메소드 실행이 종료되거나, wait() 와 같은 메소드를 만나기 전까지 유지된다.
- 다른 쓰레드들은 모니터링 락을 놓을 때 까지 대기한다.
- synchronized를 붙히지 않은 메소드는 다른 쓰레드들이 synchronized메소드를실행하면서 모니터링 락을 획득했다 하더라도, 그것과 상관없이 실행된다.
- synchronized를 메소드에 붙혀서 사용 할 경우, 메소드의 코드가 길어지면, 마지막에 대기하는 쓰레드가 너무 오래 ㅣㄱ다리는 것을 막기 위해서 메소드에 synchronized를 붙이지 않고,
문제가 있을 것 같은 부분만 synchronized 블록을 사용한다.
쓰레드와 상태제어
쓰레드가 3개가 있다면 JVM은 시간을 잘게 쪼갠 후에 한번은 쓰레드1을, 한번은 쓰레드 2를, 한번은 쓰레드3을 실행한다. 이것을 빠르게 일어나다 보니 쓰레드가 모두 동작하는 것처럼 보이는 것이다.
- 쓰레드는 실행가능상태인 Runnable과 실행상태인 Running상태로 나뉜다.
- 실행되는 쓰레드 안에서 Thread.sleep() 이나 Object가 가지고 있는 wait() 메소드가 호출이 되면 쓰레드는 블록상태가 된다.
- Thread.sleep() 은 특정시간이 지나면 자신 스스로 블록상태에서 빠져나와 Runnable 이나 Running상태가 된다.
- Object가 가지고 있는 wait() 메소드는 다른 쓰레드가 notify()나 notifyAll() 메소드를 호출하기 전에는 블록상태에서 해체되지 않는다.
- wait()메소드는 호출이 되면 모니터링 락을 놓게 된다. 그래서 대기중인 다른 메소드가 실행한다.
- 쓰레드의 run메소드가 종료되면, 쓰레드는 종료된다. 즉 Dead상태가 된다.
- Thread의 yeild메소드가 호출되면 해당 쓰레드는 다른 쓰레드에게 자원을 양보하게 된다.
- Thread가 가지고 있는 join메소드를 호출하게 되면 해당 쓰레드가 종료될 때까지 대기하게 된다.
쓰레드와 상태제어 (join)
join() 메소드는 쓰레드가 멈출 때까지 기다리게 한다.
- 일단 0.5초씩 쉬면서 숫자를 출력하는 MyThread5를 작성해 보겠다.
- 해당 쓰레드를 실행하고, 해당 쓰레드가 종료될 때 까지 기다린 후, 내용을 출력하는 joinExam 클래스
쓰레드와 상태제어 (wait, notify)
wait과 notify는 동기화된 블록 안에서 사용해야 한다. wait를 만나게 되면 해당 쓰레드는 해당 객체의 모니터링 락에 대한 권한을 가지고 있다면 모니터링 락의 권한을 놓고 대기한다.
- Thread를 상속받는 ThreadB 클래스 작성
- 이번에는 ThreadB 를 사용하며 wait 하는 클래스 작성
데몬 쓰레드
데몬(Daemon)이란 보통 리눅스와 같은 유닉스계열의 운영체제에서 백그라운드로 동작하는 프로그램을 말한다.
- 데몬쓰레드를 만뜨는 방법은 쓰레드에 데몬 설정을 하면 된다.
- 이런 쓰레드는 자바프로그램을 만들 때 백그라운드에서 특별한 작업을 처리하게 하는 용도로 만든다.
- 데몬쓰레드는 일반 쓰레드(main 등)가 모두 종료되면 강저젝으로 종료되는 특징을 가지고 있다.
댓글남기기