阻塞队列

帅比萌擦擦* 提交于 2020-02-17 20:04:37

阻塞队列

何为阻塞队列

何为阻塞队列?阻塞队列是一个队列,数据结构如下图所示:


线程1往队列里面添加元素,线程2从队列里面移除元素

  • 当队列为空时,从队列中获取元素的操作将会阻塞

  • 当队列是满时,从队列中添加元素的操作将会被阻塞

  • 试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列中添加元素

  • 试图向已满的队列中添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增

阻塞队列的用处

在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起
为什么需要BlockingQueue?
好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办了,
在concurrent包发布以前,在多线程环境下,我们每个程序员都必须自己去控制这些细节,尤其还要监护效率和线程安全,而这会给我们的程序带来不小的复杂性.

BlockingQueue

java并发包中提供了一个比较重要的阻塞队列接口供我们使用.该接口的UML图片如下:

  • ArrayBlockingQueue:由数据结构组成的有界阻塞队列
  • LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列
  • PriorityQueue:支持优先级排序的无界阻塞队列
  • DelayQueue:使用优先级队列实现的延迟无界阻塞队列
  • SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列
  • LinkedTransferQueue:由链表组成的无界阻塞队列
  • LinkedBlockingDeque:由链表组成的双向阻塞队列

BlockingQueue的核心方法

方法类型 抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take(0 poll(time,unit)
检查(即队列首元素) element() peek() 不可用 不可用
抛出异常 当阻塞队列满时,再往队列里add插入元素会抛出IllegalStateException:Queue full. 当阻塞队列为空时,再往队列里remove移除元素会抛出NoSuchElementException
特殊值 插入方法,成功true失败false. 移除方法,成功返回队列的元素,队列里灭有就返回null
一直阻塞 当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产者线程直到put数据或响应中断退出.当阻塞队里为空时,消费者线程试图从队列里take元素,队列会一直阻塞消费者线程直到队列可用
超时退出 当阻塞队列满时,队列会阻塞生产者线程一定时间,超过限时后生产者线程会退出

add(e)/remove()/element()

 1package com.atguigu.juc.MyLock;
2
3import java.util.concurrent.ArrayBlockingQueue;
4import java.util.concurrent.BlockingQueue;
5
6/**
7 * 阻塞队列
8 */

9public class BlockingQueueDemo {
10    public static void main(String[] args) throws InterruptedException {
11
12        // 初始化数组长度为3的阻塞队列
13        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
14        // 入队列
15        blockingQueue.add("a");
16        blockingQueue.add("b");
17        blockingQueue.add("c");
18        // blockingQueue.add("x"); // 抛出异常
19        System.out.println(blockingQueue.element()); // a
20
21        // 出队列
22        blockingQueue.remove();
23        blockingQueue.remove();
24        blockingQueue.remove();
25        // blockingQueue.remove(); // 抛出异常
26
27    }
28
29
30}

offer(e)/poll()/peek()

 1package com.atguigu.juc.MyLock;
2
3import java.util.concurrent.ArrayBlockingQueue;
4import java.util.concurrent.BlockingQueue;
5
6/**
7 * 阻塞队列
8 */

9public class BlockingQueueDemo {
10    public static void main(String[] args) throws InterruptedException {
11
12        // 初始化数组长度为3的阻塞队列
13        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
14        // 入队列
15        System.out.println(blockingQueue.offer("a")); // true
16        System.out.println(blockingQueue.offer("b")); // true
17        System.out.println(blockingQueue.offer("c")); // true
18        System.out.println(blockingQueue.offer("x")); // false
19        System.out.println(blockingQueue.peek()); // a
20
21        // 出队列
22        System.out.println(blockingQueue.poll()); // a
23        System.out.println(blockingQueue.poll()); // b
24        System.out.println(blockingQueue.poll()); // c
25        System.out.println(blockingQueue.poll()); // null
26
27    }
28
29
30}

put(e)/take()

 1package com.atguigu.juc.MyLock;
2
3import java.util.concurrent.ArrayBlockingQueue;
4import java.util.concurrent.BlockingQueue;
5
6/**
7 * 阻塞队列
8 */

9public class BlockingQueueDemo {
10    public static void main(String[] args) throws InterruptedException {
11
12        // 初始化数组长度为3的阻塞队列
13        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
14        // 入队列
15        blockingQueue.put("a");
16        blockingQueue.put("b");
17        blockingQueue.put("c");
18        blockingQueue.put("x"); // 队列阻塞
19    }
20}

 1package com.atguigu.juc.MyLock;
2
3import java.util.concurrent.ArrayBlockingQueue;
4import java.util.concurrent.BlockingQueue;
5
6/**
7 * 阻塞队列
8 */

9public class BlockingQueueDemo {
10    public static void main(String[] args) throws InterruptedException {
11
12        // 初始化数组长度为3的阻塞队列
13        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
14        // 入队列
15        blockingQueue.put("a");
16        blockingQueue.put("b");
17        blockingQueue.put("c");
18
19        // 出队列
20        blockingQueue.take();
21        blockingQueue.take();
22        blockingQueue.take();
23        blockingQueue.take(); // 队列阻塞
24    }
25}

offer(e,time,unit)/poll(tiem,unit)

 1package com.atguigu.juc.MyLock;
2
3import java.util.concurrent.ArrayBlockingQueue;
4import java.util.concurrent.BlockingQueue;
5import java.util.concurrent.TimeUnit;
6
7/**
8 * 阻塞队列
9 */

10public class BlockingQueueDemo {
11    public static void main(String[] args) throws InterruptedException {
12
13        // 初始化数组长度为3的阻塞队列
14        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
15        // 入队列
16        blockingQueue.offer("a"3, TimeUnit.SECONDS);
17        blockingQueue.offer("b"3, TimeUnit.SECONDS);
18        blockingQueue.offer("c"3, TimeUnit.SECONDS);
19        blockingQueue.offer("d"3, TimeUnit.SECONDS); // 线程阻塞3秒
20
21        // 出队列
22        blockingQueue.poll(3,TimeUnit.SECONDS);
23        blockingQueue.poll(3,TimeUnit.SECONDS);
24        blockingQueue.poll(3,TimeUnit.SECONDS);
25        blockingQueue.poll(3,TimeUnit.SECONDS); // 线程阻塞3秒
26    }
27}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!