[多线程]阻塞队列和生产者消费者模型

目录

1.阻塞队列

  1.1引言

1.2Java标准库中的阻塞队列

1.3自主通过Java代码实现一个阻塞队列(泛型实现)

2.生产者消费者模型


1.阻塞队列

  1.1引言

 阻塞队列是多线程部分一个重要的概念,它相比于一般队列,有两个特点:
1.线程是安全的

2.带有阻塞功能

1) 队列为空,出队列就会阻塞,阻塞到其它线程入队列为止

2)队列未满,入队列就会出现阻塞,阻塞到其它线程出队列为止

1.2Java标准库中的阻塞队列

  • ArrayBlockingQueue 是一个固定大小的阻塞队列,底层采用数组实现。当队列已经满时,插入操作将被阻塞,直到队列中有元素被取出。当队列为空时,取出操作将被阻塞,直到队列中有新元素加入。因为队列的大小是固定的,所以可以在队列未满时进行批量插入操作。

  • LinkedBlockingQueue 是一个可以无限扩容的阻塞队列,底层采用链表实现。与ArrayBlockingQueue不同,当队列满时,插入操作将被阻塞,直到有其他线程移除了队列中的元素。与ArrayBlockingQueue不同,这个队列的大小是动态变化的。

  • PriorityBlockingQueue 是一个基于优先级的阻塞队列,底层采用堆数据结构实现。每次出队的元素都是优先级最高的元素。队列中的元素必须是可比较的对象,即实现了Comparable接口。与普通队列不同,PriorityBlockingQueue不保证插入元素的顺序,而是保证在出队时优先级高的元素先出队。

1.3自主通过Java代码实现一个阻塞队列(泛型实现)

public class BlockingQueue  {
    private Object[] array;
    private int Size = 0;
    private int head;
    private int tail;
    Object object = new Object();
    public BlockingQueue(int capacity){
        array = new Object[capacity];
    }
//添加元素 如果满了就进入阻塞里面去
    public void put( T t) throws InterruptedException {
        synchronized (object) {
            while (Size >= array.length) {
                object.wait();
            }
            array[tail] = t;
            tail++;
            Size++;
            if (tail >= array.length) {
                tail = 0;
            }
            object.notify();
        }
    }
//出队列,如果为0则添加到阻塞队列里去
    public T take() throws InterruptedException {
        T t = null;
        synchronized (object) {
            while (Size == 0) {
                object.wait();
            }
             t = (T) array[head];
            head++;
            if (head >= array.length) {
                head = 0;
            }
            Size--;
            object.notify();
            return t;
        }
    }

}

2.生产者消费者模型

    生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等 待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取.
1) 阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力 .
比如在 " 秒杀 " 场景下 , 服务器同一时刻可能会收到大量的支付请求 . 如果直接处理这些支付请求 ,
服务器可能扛不住 ( 每个支付请求的处理都需要比较复杂的流程 ). 这个时候就可以把这些请求都放
到一个阻塞队列中 , 然后再由消费者线程慢慢的来处理每个支付请求 .
这样做可以有效进行 " 削峰 ", 防止服务器被突然到来的一波请求直接冲垮 .
2) 阻塞队列也能使生产者和消费者之间解耦
比如过年一家人一起包饺子 . 一般都是有明确分工 , 比如一个人负责擀饺子皮 , 其他人负责包 . 擀饺
子皮的人就是 " 生产者 ", 包饺子的人就是 " 消费者 ".
擀饺子皮的人不关心包饺子的人是谁 ( 能包就行 , 无论是手工包 , 借助工具 , 还是机器包 ), 包饺子的人
也不关心擀饺子皮的人是谁 ( 有饺子皮就行 , 无论是用擀面杖擀的 , 还是拿罐头瓶擀 , 还是直接从超
市买的 ).

2.1实际应用场景

在实际开发中,经常会用到分布式系统,服务器整个功能不是由一个服务器全部完成的,而是每个服务器负责一部分功能,通过服务器的网络通信,最终完成整个功能.

[多线程]阻塞队列和生产者消费者模型_第1张图片但是这样的话,入口服务器和用户服务器还有商品服务器之间的耦合就过大了,一旦后两个服务器出现问题,极有可能影响到入口服务器.

[多线程]阻塞队列和生产者消费者模型_第2张图片这样可以做到解耦合

你可能感兴趣的:(java,开发语言)