
put: 큐에 여유 공간이 없다면 생길때 까지 블러킹take: 큐에 값이 들어올 때까지 블러킹offer: 큐에 여유 공간이 없어 값을 추가할수 없다면 false / 여유공간이 있어 값을 추가할수 있다면 값을 추가하고 true 반환poll: 큐에 값이 없다면 null / 값이 있다면 값을 반환블러킹 큐를 사용하면 take가 알아서 멈추고 대기하기 때문에 소비자 코드를 작성하기 편리하다. 생산자 역시 소비자가 여유가 없다면 대기하게 되어 구현이 용이하다.
offer 메서드를 활용하여 값을 넣을 수 없을 경우 대기하는 것이 아니라, 부하를 분배하거나 작업 내용을 직렬화 하여 disk 에 임시로 저장한다거나 소비자 스레드 수를 조정한다거나 하는 작업도 가능함.
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) {
queue = q;
}
public void run() {
try {
while (true) {
queue.put(produce());
}
} catch (InterruptedException ex) {
// handling..
}
}
Object produce() {
// 생산
}
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) {
queue = q;
}
public void run() {
try {
while (true) {
consume(queue.take());
}
} catch (InterruptedException ex) {
// handle..
}
}
void consume(Object x) {
// 소비
}
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
// thread pool을 활용하여 더 효율적으로 할수도 있고,
// 생산자는 소비자의 상황에 맞게 값을 생성해내기 위해서는 블러킹 큐의 크기를 조절할 필요가 있음.
// 블러킹 큐의 offer 메서드를 활용하여 소비자의 상황을 보고 소비자의 수를 늘리는 등의 동적 sizing도 생각해 볼 수 있음.
// 또는 작업큐가 꽉차서 부하가 더이상 생산이 불가능 하다면 offer로 확인해보고 disk 등의 보조기억장치에 기록해두고 일을 계속 할수도 있음.
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}