阻塞式队列——生产者消费者模式


队列为满 消费者堵塞
队列为空 生产者堵塞

1.java中的阻塞式队列

import java.util.concurrent.BlockingQueue; //泛型接口

private static BlockingQueue<String> queue1 = new PriorityBlockingQueue<>(); 
  //1.堆(优先级队列)
private static BlockingQueue<String> queue2 = new LinkedBlockingQueue<>();
  //2.链表
private static BlockingQueue<String> queue3 = new ArrayBlockingQueue<>(10); 
  //3.循环队列 最大容量10

2.生产者消费者模式

生产者消费者模式:通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。

模拟测试一

条件:将阻塞队列容量设置为1,一个生产者,一个消费者。
结果:不会阻塞。

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class UseBlockingQueue {
    private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);

    private static class Producer extends Thread {
        @Override
        public void run() {
            Random random = new Random(10_000_000);
            while (true) {
                try {
                    int message = random.nextInt(100);
                    queue.put(String.valueOf(message));
                    //只有 put 和 take 有阻塞效果
                    System.out.println("放入消息: " + message);
                    Thread.sleep(random.nextInt(3) * 100);//1ms/2ms/3ms
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class Customer extends Thread {
        @Override
        public void run() {
            Random random = new Random(10_000_000);
            while (true) {
                try {
                    String message = queue.take();
                    System.out.println("收到消息: " + message);
                    Thread.sleep(random.nextInt(3) * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread producer = new Producer();//生产者
        Thread customer = new Customer();//消费者
        producer.start();
        customer.start();
    }
}

模拟测试二

条件:一个生产者,一个消费者,数组容量一。
结果:不会阻塞。

import java.util.Random;

public class MyQueue {
    private int[] array = new int[1];
    private int front = 0;
    private int rear = 0;
    private int size = 0;

    public synchronized void put(int message) throws InterruptedException {
        while (size == array.length) {
            wait();
        }

        array[rear] = message;
        rear = (rear + 1) % array.length;
        size++;
        notifyAll();
    }

    public synchronized int take() throws InterruptedException {
        while (size == 0) {
            wait();
        }

        int message = array[front];
        front = (front + 1) % array.length;
        size--;
        notifyAll();
        return message;
    }

    private static final MyQueue queue = new MyQueue();

    private static class Producer extends Thread {
        @Override
        public void run() {
            Random random = new Random();
            while (true) {
                try {
                    queue.put(random.nextInt(100));
                    System.out.println("发送消息:"+message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class Customer extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                  queue.take();
                   System.out.println("接收消息:"+message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread p1 = new Producer();
        Thread c1 = new Customer();
        p1.start();
        c1.start();

    }
}

模拟测试三

public class MyQueue2 {
    private int[] array = new int[10];
    private volatile int size = 0;
    private int front = 0;
    private int rear = 0;

    private Object full = new Object();
    private Object empty = new Object();

    public void put(int message) throws InterruptedException {
        do {
            while (size == array.length) {
                synchronized (full) {
                    full.wait();
                }
            }
            // 这里保证,size 一定是 < array.length 的
            synchronized (this) {   // 持续时间很久
                if (size == array.length) {
                    continue;
                }
                array[rear] = message;
                rear = (rear + 1) % array.length;
                size++;
            }

            synchronized (empty) {
                empty.notify();
            }
            return;
        } while (true);
    }

    public synchronized int take() throws InterruptedException {
        do {
            while (size == 0) {
                synchronized (empty) {
                    empty.wait();
                }
            }

            int message;
            synchronized (this) {   // 这句代码可能会执行很长时间
                if (size == 0) {
                    continue;
                }
                message = array[front];
                front = (front + 1) % array.length;
                size--;
            }
            synchronized (full) {
                full.notify();
            }

            return message;
        } while (true);
    }
}
发布了70 篇原创文章 · 获赞 3 · 访问量 1229

猜你喜欢

转载自blog.csdn.net/qq_43361209/article/details/104155767
今日推荐