关键:生产者不会在缓冲区满时加入数据,消费者不会在缓冲区空时消费数据
- 生产者持续生产,直到buffer满,满时阻塞;buffer不满后,继续生产
- 消费者持续消费,直到buffer空,空时阻塞;buffer不空后,继续消费
方法1: BlockingQueue实现
class Producer implements Runnable {
private BlockingQueue<Integer> queue;
private static AtomicInteger count = new AtomicInteger(0);
private static final int SLEEPTIME = 1000;
private volatile boolean isRunning = true;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
int data;
Random random = new Random();
System.out.println("start producer id = " + Thread.currentThread().getId());
while (isRunning) {
try {
Thread.sleep(random.nextInt(SLEEPTIME));
data = count.incrementAndGet();
System.out.println("producer " + Thread.currentThread().getId() + " create data:" + data
+ ", size:" + queue.size());
if (!queue.offer(data, 2, TimeUnit.SECONDS)) {
System.err.println("failed to put data: " + data);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
isRunning = false;
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
private static final int SLEEPTIME = 1000;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
Random random = new Random();
System.out.println("start consumer {id} = " + Thread.currentThread().getId());
while (true) {
try {
Thread.sleep(random.nextInt(SLEEPTIME));
if (queue.isEmpty()) {
System.out.println("Queue is empty, consumer " + Thread.currentThread().getId()
+ " is waiting, size:" + queue.size());
} else {
int data = queue.take();
System.out.println("consumer {" + Thread.currentThread().getId() + "} consume data:" + data
+ ", size:" + queue.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class BlockingQueueSolution {
public void test() {
ExecutorService executorService = Executors.newCachedThreadPool();
BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<>(20);
Producer producer1 = new Producer(blockingQueue);
Producer producer2 = new Producer(blockingQueue);
Producer producer3 = new Producer(blockingQueue);
Consumer consumer = new Consumer(blockingQueue);
executorService.submit(producer1);
executorService.submit(producer2);
executorService.submit(producer3);
executorService.submit(consumer);
try {
Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
producer1.stop();
producer2.stop();
producer3.stop();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
public class ProducerConsumer {
public static void main(String[] args) {
BlockingQueueSolution blockingQueueSolution = new BlockingQueueSolution();
blockingQueueSolution.test();
}
}