본문 바로가기

Programming/JAVA

멀티 스레드(6) - 스레드 상태 제어 5 : 스레드 간 협업 3

 

 

 

 

 

또 하나의 스레드 간 협업 예제를 작성해 보겠습니다. 조금 복잡하지만 차례차례 읽어보겠습니다. 

 

- 우선 데이터를 저장하는 생산자 스레드가 있습니다. 

- 이 생산자 스레드는 공유 객체(DataBox)에 데이터를 저장합니다. 

- 그럼 소비자 스레드에서는 이 데이터를 읽어들입니다. 

- 이 과정을 순서대로 교대하며 진행하는 작업을 구현해야 합니다. 

- 단, 제약 사항이 있습니다. 생산자 스레드는 소비자 스레드가 읽기 전에 새 데이터를 두 번 생성 불가합니다.

  > setData( ) 메서드 두 번 실행 불가

- 동일하게 소비자 스레드도 새로운 데[이터 생성 전에 데이터를 두 번 읽어서도 안됩니다. 

  > getData( ) 메서드 두 번 실행 불가

 

구현은 실제로 다음과 같이 진행합니다. 공유 객체(DataBox)에 데이터를 저장할 수 있는 data 필드 값(String)이 null이면 생산자 스레드를 실행 대기 상태 - 소비자 스레드는 일시 정지 상태로 만듭니다. 반대로 data 필드의 값이 null이 아니라면 소비자 스레드를 실행 대기 상태로 만들고, 생산자 스레드를 일시 정지 상태로 만듭니다. 

 

public class DataBox {
	private String data;
	
	public synchronized String getData() {
		// data필드가 null이면 소비자 스레드를 일시 정지 상태로 만듬
		if(this.data == null) {
			try {
				wait();
			} catch(InterruptedException e) {}
		}
		
		String returnValue = data;
		System.out.println("ConsumerThread가 읽은 데이터: " + returnValue);
		
		// data 필드를 null로 만들고 생산자 스레드를 실행 대기 상태로 만듬
		data = null;
		notify();
		
		return returnValue;
	}
	
	public synchronized void setData(String data) {
		// data 필드가 null이 아니면 생산자 스레드를 일시 정지 상태로 만듬
		if(this.data != null) {
			try {
				wait();
			} catch(InterruptedException e) {}
		}
		
		// data 필드에 값을 저장하고 소비자 스레드를 실행 대기 상태로 만듬
		this.data = data;
		System.out.println("ProducerThread가 생성한 데이터: " + data);
		notify();
	}
}

 

 

// 데이터를 생산(저장)하는 스레드
// ProducerThread.java
public class ProducerThread extends Thread {
	private DataBox dataBox;
	
	public ProducerThread(DataBox dataBox) {
		// 공유 객체를 필드에 저장한다
		this.dataBox = dataBox;
	}
	
	@Override
	public void run() {
		for(int i = 1; i <= 3; i++) {
			String data = "Data-" + i;
			dataBox.setData(data);
		}
	}
}

 

 

// 데이터를 소비하는(읽는) 스레드
// ConsumerThread.java
public class ConsumerThread extends Thread {
	private DataBox dataBox;

	public ConsumerThread(DataBox dataBox) {
		this.dataBox = dataBox;
	}
	
	@Override
	public void run() {
		for(int i = 1; i <= 3; i++) {
			String data = dataBox.getData();
		}
	}
}

 

 

public class ExampleMain {
	public static void main(String[] args) {
		DataBox dataBox = new DataBox();
		
		ProducerThread producerThread = new ProducerThread(dataBox);
		ConsumerThread consumerThread = new ConsumerThread(dataBox);
		
		producerThread.start();
		consumerThread.start();
	}
}

/* 출력
ProducerThread가 생성한 데이터: Data-1
ConsumerThread가 읽은 데이터: Data-1
ProducerThread가 생성한 데이터: Data-2
ConsumerThread가 읽은 데이터: Data-2
ProducerThread가 생성한 데이터: Data-3
ConsumerThread가 읽은 데이터: Data-3
*/