Programming/Java

Producer/Consumer 예제

Lawmin 2011. 6. 20. 17:10
두 곳의 데이터 소스에서 입력을 받는 동안 사이사이 두 입력값의 동일성을 비교해서 화면에 나타내려고 할 때 사용한 Thread 처리 방식이다.
Consumer는 데이터가 없으면 대기하다가, Producer가 데이터를 입력해서 생기면 비교하고 결과를 리턴하는데, 종료 처리는, 두개의 Producer가 생성을 마쳤는지를 검사하다가 interrupt 하게 된다.
쉽게 말해, 두 명의 제빵사가 빵을 만들고 빵 나올때까지 손님이 기다리는 상황인데 빵이 나오면, 손님은 빵을 바로 집고 또 기다린다. 두 명 모두 빵을 다 찍어내면(영업 끝나면) 손님보고 나가라고 interrupt 한다.

[Main.java]
package pc;

public class Main {
public static void main(String[] args) throws InterruptedException {
Data d = new Data();
Producer[] p = new Producer[2];
Consumer c = null;
for(int i = 0; i < 2; ++i) {
p[i] = new Producer(i, d);
}
c = new Consumer(d);
for(int i = 0; i < 2; ++i) {
p[i].start();
}
c.start();
while(p[0].isAlive() || p[1].isAlive()) {
Thread.sleep(10);
}
c.interrupt();
}
}

[Producer.java]
package pc;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Producer extends Thread {
private final List prodList;
private final Data data;
private final int id;
private int rowNum;
private Random r = new Random();
public Producer(int id, Data data) {
rowNum = 0;
this.prodList = new ArrayList();
this.data = data;
this.id = id;
if(id == 0) {
List cols = new ArrayList();
cols.add("1"); prodList.add(cols);
cols = new ArrayList();
cols.add("2"); prodList.add(cols);
cols = new ArrayList();
cols.add("3"); prodList.add(cols);
cols = new ArrayList();
cols.add("4"); prodList.add(cols);
cols = new ArrayList();
cols.add("9"); prodList.add(cols);
cols = new ArrayList();
cols.add("6"); prodList.add(cols);
cols = new ArrayList();
cols.add("7"); prodList.add(cols);
cols = new ArrayList();
cols.add("8"); prodList.add(cols);
cols = new ArrayList();
cols.add("5"); prodList.add(cols);
}
else {
List cols = new ArrayList();
cols.add("1"); prodList.add(cols);
cols = new ArrayList();
cols.add("2"); prodList.add(cols);
cols = new ArrayList();
cols.add("3"); prodList.add(cols);
cols = new ArrayList();
cols.add("4"); prodList.add(cols);
cols = new ArrayList();
cols.add("5"); prodList.add(cols);
cols = new ArrayList();
cols.add("6"); prodList.add(cols);
cols = new ArrayList();
cols.add("7"); prodList.add(cols);
cols = new ArrayList();
cols.add("8"); prodList.add(cols);
cols = new ArrayList();
cols.add("9"); prodList.add(cols);
}
}
public void run() {
try {
while(rowNum < 9) {
data.addRow(id, (List)prodList.get(rowNum++));
sleep(r.nextInt(1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

[Consumer.java]
package pc;

import java.util.Random;

public class Consumer extends Thread {
private final Data data;
private int rowNum;
private Random r = new Random();
public Consumer(Data data) {
this.data = data;
}
public void run() {
try {
while(true) {
System.out.println(data.compare());
sleep(r.nextInt(1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
 
[Data.java]
package pc;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Data {
public List[] colTypes = new List[2];
public List[] colNames = new List[2];
public List[] colRows = new List[2];
private int currentRow;

public Data() {
for(int i = 0; i < 2; ++i) {
colTypes[i] = Collections.synchronizedList(new ArrayList());
colNames[i] = Collections.synchronizedList(new ArrayList());
colRows[i] = Collections.synchronizedList(new ArrayList());
}
currentRow = 0;
}
public synchronized void addRow(int index, List rowData) throws InterruptedException {
colRows[index].add(rowData);
notifyAll();
}
public synchronized boolean compare() throws InterruptedException {
while(!(currentRow < colRows[0].size()) || !(currentRow < colRows[1].size()))
wait();
boolean isEqual = colRows[0].get(currentRow).equals(colRows[1].get(currentRow));
++currentRow;
return isEqual;
}
}