본문
160103P(일)
Java - Chapter 18 멀티스레드 프로그래밍
스레드(thread)
한 가닥 실
명령문이 실행되는 순서를 따라가다 보면 길게 연결된 한 가닥 실과 같은 흐름이 있다.
1. java.lang.Thread
class MultithreadExample1 {
public static void main(String args[]) {
Thread thread = new DigitTread();
thread.start();
...
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
class DigitThread extends Thread {
public void run() {
...
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
2. java.lang.Runnable
class MulithreadExample3 {
public static void main(String args[]) {
Thread thread = new Thread(new SmallLetters());
thread.start();
...
}
}
class SmallLetters implements Runnable {
public void run() {
...
}
}
스레드간의 커뮤니케이션
공유메모리의 데이터를 두 개 이상의 스레드가 서로 공유 할 때
class SharedArea {
double result;
}
class MultithreadExample4 {
public static void main(String args[]) {
CalcThread thread1 = new CalcThread();
PrintThread thread2 = new PrintThread();
SharedArea obj = new SharedArea();
thread1.sharedArea = obj;
thread2.sharedArea = obj;
thread1.start();
thread2.start();
}
}
class CalcThread extends Thread {
SharedArea = sharedArea;
public void run() {
...
sharedArea.result = total * 4;
}
}
class PrintThread extends Thread {
SharedArea sharedArea;
public void run() {
...
System.out.println(sharedArea.result);
}
}
스레드간의 문제 - resutl에 데이터를 쓰기도 전에 thread2가 출력해버린다.
1. SharedArea 클래스에 데이터 유무를 표시하는 필드를 추가
class SharedArea {
double result;
boolean isReady;
}
class MultithreadExample4 {
public static void main(String args[]) {
CalcThread thread1 = new CalcThread();
PrintThread thread2 = new PrintThread();
SharedArea obj = new SharedArea();
thread1.sharedArea = obj;
thread2.sharedArea = obj;
thread1.start();
thread2.start();
}
}
class CalcThread extends Thread {
SharedArea = sharedArea;
public void run() {
...
sharedArea.result = total * 4;
sharedArea.isReady = true;
}
}
class PrintThread extends Thread {
SharedArea sharedArea;
public void run() {
...
while(sharedArea.isReady != true) {
continue;
}
System.out.println(sharedArea.result);
}
}
∴ 굉장히 비효율적인 방법이다.
어떤 자바 컴파일러는 프로그램 성능 향상을 위해서 변수의 값을 바꾸지 않고 반복해서 체크할 경우에는 그 값을 한번 가져다 놓고 여러 번 사용하도록 최적화 한다. 따라서 volatile(휘발성)을 키워드를 붙이면 된다.
class SharedArea {
double result;
volatile boolean isReady;
}
2. Thread.sleep() 메소드를 사용해서 필드값을 쓰는 시간을 벌어주면 된다.
∴ 더 좋은 방법은 ciritical section 동기화!
3. critical section synchronization
critical section이 실행되는 동안 다른 스레드가 공유 데이터를 사용할 수 없도록 만드는 것
class SharedArea {
Account account1;
Account account2;
}
class MultithreadExample5 {
public static void main(String args[]) {
SharedArea area = new SharedArea();
...
}
}
class TransferThread extends Thread {
SharedArea sharedArea;
TransferThread(SharedArea area) {
sharedArea = area;
}
public void run() {
...
synchronized(sharedArea) {
sharedArea.account1.withdraw(100000);
sharedArea.account2.deposit(100000);
}
}
}
class PrintThread extends Thread {
SharedArea sharedArea;
PrintThread(SharedArea area) {
sharedArea = area;
}
public void run() {
...
synchronized(sharedArea) {
int sum = sharedArea.account1.balance + sharedArea.account2.balance;
}
try {
Thread.sleep(1);
} catch(InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
동기화 영역 지정
synchronized (공유_객체) {
ciritical section
}
동기화 메소드
1.
class SharedArea {
Account account1;
Account account2;
void transfer(int amount) {
synchronized(this) {
...
}
}
}
2.
class SharedArea {
Account account1;
Account account2;
synchronized void transfer(int amount) {
...
}
}
스레드간의 신호 전송
반드시 동기화블록이나 동기화 메소드 내에서 사용해야 한다.
notify
다른 스레드에게 신호를 보내는 메소드
wait
notify 신호가 오기를 기다리는 메소드
class CalcThread extends Thread {
...
public void run() {
synchronized(obj) {
obj.notify();
}
}
}
class PrintThread extends Thread {
...
public void run() {
synchronized(obj) {
obj.wait();
}
}
}
한꺼번에 신호 보내기
class CalcThread extends Thread {
...
public void run() {
synchronized(obj) {
obj.notifyAll();
}
}
}
스레드의 상태
New Thread(run 메소드에 진입 전) -> Runnable or Not Runnable -> Dead Thread
Not Runnable
wait나 sleep 등 실행 불가능 상태
스레드의 상태를 알아내는 메소드
Thread.State state = thread.getState();
State
열거타입
NEW - 실행되기 전
RUNNABLE - 실행 가능 상태
WAITING - wait 메소드 호출 상태
TIME_WAITING - sleep 메소드 호출 상태
BLOCKED - synchronized 끝나기를 기다리는 상태
TERMINATED - 실행 마친 상태
class MonitorThread extends Thread {
Thread thread;
MonitorThread(Thread thread) {
this.thread = thread;
}
public void run() {
while(true) {
Thread.State state = thread.getState();
if(state == Thread.State.TERMINATED) {
break;
}
try {
Thread.sleep(2000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread 고급
뮤텍스와 세마포어
http://topnanis.tistory.com/195
뮤텍스(MUTual EXclution : MUTEX)
synchronized로 뮤텍스 락(mutex-lock)를 해줌으로써 구현한다.
세마포어(Semaphore)
1. wait, notifyAll로 구현
2. java.util.concurrent.Semaphore의 acquire(), release()로 구현
http://gladtosee.tistory.com/191
∴ JAVA 디자인 패턴 책을 하나 봐야할 것 같다.
'Programming > Java' 카테고리의 다른 글
160117P(일) (0) | 2016.01.17 |
---|---|
160109P(토) (0) | 2016.01.10 |
160108P(금) (0) | 2016.01.09 |
160107P(목) (0) | 2016.01.07 |
151220P(일) (0) | 2015.12.20 |
댓글