直接给出代码实现:
import java.util.LinkedList;
import java.util.Queue;
public class ProducerAndConsumer {
public int queueCapacity;
public Queue<Integer> queue = new LinkedList<>();
ProducerAndConsumer(int queueCapacity){
this.queueCapacity = queueCapacity;
}
class producer implements Runnable {
@Override
public void run() {
synchronized (queue) {
//如果队列满了,那么此时生产者应该阻塞
while(true){
while(queue.size() == queueCapacity){
try {
System.out.println("生产者阻塞了");
queue.wait();
System.out.println("生产者被唤醒咯");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer(1);
System.out.println("生产者向队列取中插入一个元素,队列已有元素个数:"+(queue.size()));
queue.notify();
}
}
}
}
class consumer implements Runnable {
@Override
public void run() {
synchronized (queue) {
while(true){
//如果队列满了,那么此时生产者应该阻塞
while(queue.size() == 0){
try {
System.out.println("消费者阻塞了");
queue.wait();
System.out.println("消费者被唤醒咯");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
System.out.println("生产者向队列取中取走 一个元素,队列剩余空间:"+(ProducerAndConsumer.this.queueCapacity-queue.size()));
queue.notify();
}
}
}
}
public static void main(String[] args) {
ProducerAndConsumer pc = new ProducerAndConsumer(10);
Thread t1 = new Thread(pc.new consumer());
Thread t2 = new Thread(pc.new producer());
t1.start();
t2.start();
}
}
测试结果如下:
生产者被唤醒咯
生产者向队列取中插入一个元素,队列已有元素个数:1
生产者向队列取中插入一个元素,队列已有元素个数:2
生产者向队列取中插入一个元素,队列已有元素个数:3
生产者向队列取中插入一个元素,队列已有元素个数:4
生产者向队列取中插入一个元素,队列已有元素个数:5
生产者向队列取中插入一个元素,队列已有元素个数:6
生产者向队列取中插入一个元素,队列已有元素个数:7
生产者向队列取中插入一个元素,队列已有元素个数:8
生产者向队列取中插入一个元素,队列已有元素个数:9
生产者向队列取中插入一个元素,队列已有元素个数:10
生产者阻塞了
消费者被唤醒咯
生产者向队列取中取走 一个元素,队列剩余空间:1
生产者向队列取中取走 一个元素,队列剩余空间:2
生产者向队列取中取走 一个元素,队列剩余空间:3
生产者向队列取中取走 一个元素,队列剩余空间:4
生产者向队列取中取走 一个元素,队列剩余空间:5
生产者向队列取中取走 一个元素,队列剩余空间:6
生产者向队列取中取走 一个元素,队列剩余空间:7
生产者向队列取中取走 一个元素,队列剩余空间:8
生产者向队列取中取走 一个元素,队列剩余空间:9
生产者向队列取中取走 一个元素,队列剩余空间:10
消费者阻塞了
生产者被唤醒咯
生产者向队列取中插入一个元素,队列已有元素个数:1
生产者向队列取中插入一个元素,队列已有元素个数:2
生产者向队列取中插入一个元素,队列已有元素个数:3
生产者向队列取中插入一个元素,队列已有元素个数:4
生产者向队列取中插入一个元素,队列已有元素个数:5
生产者向队列取中插入一个元素,队列已有元素个数:6
生产者向队列取中插入一个元素,队列已有元素个数:7
生产者向队列取中插入一个元素,队列已有元素个数:8
生产者向队列取中插入一个元素,队列已有元素个数:9
生产者向队列取中插入一个元素,队列已有元素个数:10
生产者阻塞了
消费者被唤醒咯
生产者向队列取中取走 一个元素,队列剩余空间:1
生产者向队列取中取走 一个元素,队列剩余空间:2
生产者向队列取中取走 一个元素,队列剩余空间:3
生产者向队列取中取走 一个元素,队列剩余空间:4
生产者向队列取中取走 一个元素,队列剩余空间:5
生产者向队列取中取走 一个元素,队列剩余空间:6
生产者向队列取中取走 一个元素,队列剩余空间:7
生产者向队列取中取走 一个元素,队列剩余空间:8
生产者向队列取中取走 一个元素,队列剩余空间:9
生产者向队列取中取走 一个元素,队列剩余空间:10
消费者阻塞了
生产者被唤醒咯
生产者向队列取中插入一个元素,队列已有元素个数:1
生产者向队列取中插入一个元素,队列已有元素个数:2
生产者向队列取中插入一个元素,队列已有元素个数:3
生产者向队列取中插入一个元素,队列已有元素个数:4
生产者向队列取中插入一个元素,队列已有元素个数:5
生产者向队列取中插入一个元素,队列已有元素个数:6
生产者向队列取中插入一个元素,队列已有元素个数:7
生产者向队列取中插入一个元素,队列已有元素个数:8
生产者向队列取中插入一个元素,队列已有元素个数:9
生产者向队列取中插入一个元素,队列已有元素个数:10
生产者阻塞了
消费者被唤醒咯
生产者向队列取中取走 一个元素,队列剩余空间:1
生产者向队列取中取走 一个元素,队列剩余空间:2
生产者向队列取中取走 一个元素,队列剩余空间:3
生产者向队列取中取走 一个元素,队列剩余空间:4
生产者向队列取中取走 一个元素,队列剩余空间:5
生产者向队列取中取走 一个元素,队列剩余空间:6
生产者向队列取中取走 一个元素,队列剩余空间:7
生产者向队列取中取走 一个元素,队列剩余空间:8
生产者向队列取中取走 一个元素,队列剩余空间:9
生产者向队列取中取走 一个元素,队列剩余空间:10
消费者阻塞了
生产者被唤醒咯
生产者向队列取中插入一个元素,队列已有元素个数:1
生产者向队列取中插入一个元素,队列已有元素个数:2
生产者向队列取中插入一个元素,队列已有元素个数:3
生产者向队列取中插入一个元素,队列已有元素个数:4
生产者向队列取中插入一个元素,队列已有元素个数:5
生产者向队列取中插入一个元素,队列已有元素个数:6
生产者向队列取中插入一个元素,队列已有元素个数:7
生产者向队列取中插入一个元素,队列已有元素个数:8
生产者向队列取中插入一个元素,队列已有元素个数:9
生产者向队列取中插入一个元素,队列已有元素个数:10
生产者阻塞了
以上是不使用阻塞队列的方式,所以我们只能自己使用wait和nofity机制来实现线程的阻塞,下面我们尝试用阻塞队列来实现::
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerAndConsumerWithBlockedQueue {
private int queueSize = 10;
private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(queueSize);
public static void main(String[] args) {
ProducerAndConsumerWithBlockedQueue test = new ProducerAndConsumerWithBlockedQueue();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
Random random = new Random();
@Override
public void run() {
consume();
}
private void consume() {
while(true){
try {
queue.take();
System.out.println("从队列取走一个元素,队列目前存在"+queue.size()+"个元素");
Thread.sleep(random.nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{
Random random = new Random();
@Override
public void run() {
produce();
}
private void produce() {
while(true){
try {
queue.put(1);
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
Thread.sleep(random.nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}