阻塞队列(BlockingQueue)

阻塞队列(BlockingQueue)

image


  • 阻塞队列都实现了:BlockingQueue
  • JDK提供的七个阻塞队列
    image

一、特点

1、JDK提供的七个阻塞队列简介

①. ArrayBlockingQueue

有界 阻塞队列——必须指定大小——数组

②. LinkedBlockingQueue

有界 阻塞队列——默认大小:Integer.MAX_VALUE最大值——链表

③. LinkedTransferQueue

无界 阻塞队列——链表

④. PriorityBlockingQueue

无界 阻塞队列——支持优先级排序

⑤. DelayQueue

无界 阻塞队列——使用优先级队列实现的

⑥. SynchronousQueue

不存储元素 的阻塞队列

⑦. LinkedBlockingDeque

双端 阻塞队列——链表

2、其他特点

  • 阻塞队列默认情况下是FIFO(先进先出)PriorityBlockingQueue可以设置优先级出队列
  • BlockingQueue 不接受 null 元素。试图 add、put 或 offer 一个 null 元素时,某些实现会抛出 NullPointerException。null 被用作指示 poll 操作失败的警戒值。
  • BlockingQueue 实现是线程安全

二、阻塞队列的方法

  • e 表示插入到队列的元素
  • 其他特殊的方法,见参考。
  • 常用方法
阻塞队列的核心方法有以下几组
1.抛异常组:add(),remove(),element();
2.返回布尔值组:offer(),poll(),peek();
3.阻塞组:put(),take();
4.超时组:offer(),poll();

1、插入元素

描述 抛出异常 一直阻塞 返回特殊的值 超时退出
插入数据 add(e) put(e) offer(e)
推荐
offer(e, time, unit)
推荐
插入成功 返回true 无返回值 返回true 返回true
插入失败
(队列满)
抛异常 一直阻塞,直到插入元素 返回false 等10秒(假如设置的10s)
然后放弃插入返回false
可用于控制添加元素的速度

2、获取元素——并移除队列的头元素

描述 抛出异常 一直阻塞 返回特殊的值 超时退出
获取元素 remove() take() poll() poll(time, unit)
获取成功 返回元素 返回元素 返回元素 返回元素
获取失败
(队列空)
抛异常 一直阻塞,直到获取到元素 返回null 等10秒(假如设置的10s)
然后null
可用于控制消费的速度

3、获取元素——不移除队列的元素

描述 抛出异常 返回特殊的值
获取元素 element() peek()
获取成功 返回元素 返回元素
获取失败
(队列空)
抛异常 返回null

4、推荐使用

  • 一般情况下 offer() 和 poll() 方法配合使用

程序中常用的是 offer() 和 poll() 方法,因为这两个方法比较友好,不会报错

  • put() 和 take() 阻塞方法配合使用
  • add() 和 remove() 方法会配合使用

5、测试

  • 自己去测
package com.cc.testproject.utils;

import java.time.LocalDateTime;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * <p>存放队列</p>
 *
 * @author --
 * @since 2024/1/9
 */
public class Task01 {

    //有界阻塞队列——FIFO(先进先出)——必须指定大小——数组
    private static final ArrayBlockingQueue<String> QUEUE1 = new ArrayBlockingQueue<>(1);
    //有界阻塞队列——FIFO(先进先出)——默认大小:int最大值——链表
    private static final LinkedBlockingQueue <String> QUEUE2 = new LinkedBlockingQueue<>();
    //无界阻塞队列——FIFO(先进先出)——无限大——链表
    private static final LinkedTransferQueue <String> QUEUE3 = new LinkedTransferQueue<>();

    public static void main(String[] args) throws InterruptedException {

        boolean offer = QUEUE1.offer("1");
        System.out.println("第1次添加:" + offer + "-时间:" + LocalDateTime.now());
        boolean offer1 = QUEUE1.offer("2");
        System.out.println("第2次添加:" + offer1 + "-时间:" + LocalDateTime.now());

        System.out.println(QUEUE1.take());

//        System.out.println(QUEUE1.element());
        System.out.println(QUEUE1.peek());
        System.out.println(QUEUE1);

//        System.out.println(QUEUE1.poll(5, TimeUnit.SECONDS));
//        System.out.println(QUEUE1.poll());
//        System.out.println(QUEUE1.remove());
//        System.out.println(QUEUE1.take());

//        System.out.println(QUEUE1.remove());
//        System.out.println(QUEUE1.remove());
//        System.out.println(QUEUE1.take());
//        System.out.println(QUEUE1.take());
//        System.out.println(QUEUE1.poll());
//        System.out.println(QUEUE1.poll(5, TimeUnit.SECONDS));

        //如队列满:等10秒,然后放弃插入,返回false
//        boolean offer = QUEUE1.offer("1", 10, TimeUnit.SECONDS);
//        System.out.println("第1次添加:" + offer + "-时间:" + LocalDateTime.now());
//        boolean offer1 = QUEUE1.offer("2", 10, TimeUnit.SECONDS);
//        System.out.println("第2次添加:" + offer1 + "-时间:" + LocalDateTime.now());
//
//        System.out.println("添加完成:" + QUEUE1);

        // 如队列满:抛异常
//        boolean add1 = QUEUE1.add("1");
//        System.out.println("第1次添加:" + add1);
//        boolean add2 = QUEUE1.add("2");
//        System.out.println("第2次添加:" + add2);

        //如队列满:一直等
//        QUEUE1.put("1");
//        System.out.println("第1次添加:" + LocalDateTime.now());
//        QUEUE1.put("2");
//        System.out.println("第2次添加:" + LocalDateTime.now());
    }
}

三、使用场景、个人理解

1、使用场景

  • 需要顺序执行,且是耗时操作,可用来装用户的请求

  • 阻塞队列在多线程编程中有许多使用场景,包括但不限于:

  1. 生产者-消费者模式:用于在生产者和消费者之间进行线程安全的数据交换。
  2. 任务调度:用于实现线程池中的任务队列,控制任务的提交和执行。
  3. 数据传输:用于在不同线程之间传递数据,例如在生产者和消费者之间传递数据。
  4. 事件驱动编程:用于在事件处理中进行线程间通信和协调。
  5. 限流和流量控制:用于控制系统的并发访问量,防止系统过载。

image

2、个人理解

  • 阻塞队列之所以叫阻塞队列,是因为它可以在添加或者获取元素的时候阻塞添加或获取的线程。直到线程达到自己的目的。
  • 阻塞队列之所以被称为阻塞队列,是因为当队列已满时,尝试向队列中添加元素的线程会被阻塞,直到队列有空间为止;当队列为空时,尝试从队列中获取元素的线程会被阻塞,直到队列中有元素为止。这种行为可以确保线程安全地在队列中添加或获取元素。

四、参考:

image

posted on 2024-01-09 17:39  C_C_菜园  阅读(77)  评论(0编辑  收藏  举报

导航