정리노트

[자바/java] thread 간 동작조정(생산자, 소비자) 본문

프로그래밍/Java

[자바/java] thread 간 동작조정(생산자, 소비자)

Rolen 2023. 2. 4. 16:31

생산자는 데이터를 생산하고 소비자는 데이터를 소비하도록 동작을 조정한다.

두 thread는 공유된 객체를 사용하는데

생산을 하지 않았는데 소비를 하려고 하거나

소비를 하지 않았는데 생산을 하려고 시도하면 안된다.

 

그래서 소비가 되었는지, 생산이 되었는지를 확인하기 위해 각 thread가 계속 동작상태가 된다면 엄청난 CPU낭비가 된다.

 

따라서, 동작을 잠시 멈추는 wait() 과 동작하도록 깨우는 notifyAll()을 사용한다.

wait(), notifyAll() 사용 / 미사용

     

package producerConsumerTest;

class Buffer {
	private int data;
	private boolean empty = true;
	
	public synchronized int get() {
		while(empty) {
			try {
				wait();
			} catch (InterruptedException e) {}
		}
		empty = true;	// 생산된 데이터 사용 후 비었음 설정
		notifyAll();	// 생성자 깨움
		return data;
	}
	
	public synchronized void put(int data) {
		while(!empty) {
			try {
				wait();
			} catch (InterruptedException e) {}
		}
		empty = false;		// 데이터 생산 후 채움
		this.data = data;	// 데이터 저장
		notifyAll();		// 소비자 깨움
	}
}

class Producer implements Runnable {
	private Buffer buffer;
	public Producer(Buffer buffer) {
		this.buffer = buffer;
	}
	public void run() {
		for (int i = 0; i < 10; i++) {
			buffer.put(i);	// buffer에 데이터를 넣는다.
			System.out.printf("생산자: %d번 케이크를 생산하였습니다.%n", i);
			try {
				Thread.sleep((int) (Math.random() * 100));
			} catch (InterruptedException e) {	}
		}
	}
}

class Consumer implements Runnable {
	private Buffer buffer;
	public Consumer(Buffer drop) {
		this.buffer = drop;
	}
	public void run() {
		for (int i = 0; i < 10; i++) {
			int data = buffer.get();	// buffer의 데이터를 가져온다.
			System.out.printf("소비자: %d번 케이크를 소비하였습니다.%n", data);
			try {
				Thread.sleep((int)(Math.random() * 100));
			} catch (InterruptedException e) {  }
		}
	}
}
public class ProducerConsumerTest {

	public static void main(String[] args) {
		Buffer buffer = new Buffer();
		new Thread(new Producer(buffer)).start();
		new Thread(new Consumer(buffer)).start();
	}

}

 

 

728x90