-SyncStack 클래스
- 공유데이터를 담는 Vector 타입의 buffer 필드
- buffer 에서 데이터를 꺼내는 pop () 메서드
- buffer 에서 데이터를 집어넣는 push () 메서드
-Producer 클래스
- Runnable 인터페이스의 run() 메서드를 구현함.
- 데이터를 집어넣은 행위를 실행하는 클래스
-Consumer 클래스
- Runnable 인터페이스의 run() 메서드를 구현함.
- 데이터를 꺼내는 행위를 실행하는 클래스
각 객체 (Producer, Consumer)들을 쓰레드 객체에 담아 병렬적으로 수행함. (멀티 쓰레드)
배열 안에서 데이터들이 각 객체들로 인해 값이 추가되고 제거되는 프로그램이 됨.
그 과정에서 발생할 수 있는 데이터 유실을 방지하고자 synchronized 키워드 사용.
public class Producer implements Runnable {
private SyncStack theStack;
private int num;
private static int counter = 1;
public Producer (SyncStack s) {
theStack = s;
num = counter++;
}
public void run() {
char c;
for (int i = 0; i < 200; i++) {
c = (char)(Math.random() * 26 +'A'); // A~Z
theStack.push(c); //c의 값을 랜덤하게 추가함.
System.out.println("Producer" +num+ ": " +c);
try {
Thread.sleep((int)(Math.random() * 300)); //0~300밀리초 랜덤하게 슬립함.
} catch (InterruptedException e) {
// ignore it
}
}
}
}
public class Consumer implements Runnable {
private SyncStack theStack;
private int num;
private static int counter = 1;
public Consumer (SyncStack s) {
theStack = s;
num = counter++;
}
public void run() {
char c;
for (int i = 0; i < 200; i++) {
c = theStack.pop(); //c의 값을 랜덤하게 꺼냄.
System.out.println("Consumer"+num+": " +c);
try {
Thread.sleep((int)(Math.random() * 300));
} catch (InterruptedException e) {
}
} // for
} // run
}
import java.util.Vector;
public class SyncStack {
//데이터 값을 담는 monitor객체
private Vector buffer = new Vector(400, 200);
// 값을 꺼내는 것
public synchronized char pop() {
while (buffer.size() <=0) {
try {
this.wait(); //사이즈가 0이면, not-runnable 상태로 만듬.
} catch (InterruptedException e) {
e.printStackTrace(); //예외 발생 했을 때 스택 내용을 출력
}
}
char c;
// synchronized(this){ // this 대신 buffer 사용가능
c = (char) buffer.remove(buffer.size()-1); //데이터 하나를 꺼내서 제거
// }
return c;
}
// 값을 넣는 것
public synchronized void push(char c) {
buffer.addElement(c);
this.notify(); // not- runnable 상태의 쓰레드를 runnable 상태로 만듬.
}
}
public class SyncTest {
public static void main(String[] args) {
//벡터로 구현
SyncStack stack = new SyncStack();
//쓰레드 1
Producer p1 = new Producer(stack);
Thread prodT1 = new Thread (p1);
prodT1.start();
//쓰레드 2
Producer p2 = new Producer(stack);
Thread prodT2 = new Thread (p2);
prodT2.start();
//쓰레드 3
Consumer c1 = new Consumer(stack);
Thread consT1 = new Thread (c1);
consT1.start();
//쓰레드 4
Consumer c2 = new Consumer(stack);
Thread consT2 = new Thread (c2);
consT2.start();
}
}
-쓰레드는 예외(Exception)이 발생하면 죽어버리게 됨. (like 개복치)
-pop()메서드에서 wait()메서드를 사용하지 않으면, 배열 안에 데이터 값이 없는 상태에서 remove()메서드를 실행하게 되어 예외가 발생하게 된다. (ArrayIndexOutOfBoundsException)
∴ 따라서 배열 안에 값이 없는지 확인하여 없을 경우 wait()로 Not-Runnable 상태로 한 다음 push()메서드로 데이터 값이 추가된 후, notify()메서드를 통해 Not-Runnable 상태의 쓰레드를 다시 Runnable 상태로 회복하여 예외를 처리.
'연습문제 및 실습 자료' 카테고리의 다른 글
재귀함수 호출 연습문제 (0) | 2023.08.22 |
---|---|
정렬 만들기 (0) | 2023.08.22 |
쓰레드 (0) | 2023.08.18 |
날짜 클래스 만들기 - 일정관리 프로그램(1) (0) | 2023.08.17 |
아이스크림 심부름 문제 - 기초 알고리즘 (0) | 2023.08.16 |