【问题一】熟悉阻塞队列的概念
队列:先到先得
阻塞队列:首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致是:线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素。
1.当阻塞队列是空时,从队列中获取元素的操作将被阻塞
2.当阻塞队列是满时,往队列里添加元素的操作将被阻塞
试图从空的阻塞队列中获取元素的线程将会阻塞,直到其他的线程往空的队列中插入新的元素。试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他线程从队列中移除一个或多个元素或者多个元素或者完全清空队列后使队列重新变得空闲起来并后续新增。
【问题二】为什么用?有什么好处
上面知道了什么是阻塞队列,那到底有什么用
传统情况下若是等待和唤醒,是需要一些关键字。wait不许做,线程停止;notify all线程被唤醒,不用控制wait或者notify
在多线程领域,所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦满足条件,被挂起的线程又会自动被唤醒。
为什么需要队列(BlockingQueue)呢?
好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你包办了。在concurrent包发布之前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给程序带来不小的复杂度。
【阻塞队列的核心方法认识BlockingQueue核心方法】
【架构介绍】
BlockingQueue和list都是Collections的接口
种类分析 | ArrayBlockingQueue:由数组结构组成的有界阻塞队列 | |||
LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列。 | ||||
PriorityBlockingQueue:支持优先级排序的无界阻塞队列。 | ||||
DelayQueue:使用优先级队列实现的延迟无界阻塞队列。 | ||||
SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列。 | ||||
LinkedTransferQueue:由链表结构组成的无界阻塞队列。 | ||||
LinkedBlockingDeque:由链表结构组成的双向阻塞队列。 |
【问题三】队列demo实现
package com.neu.controller.study;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/*
* ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序
* LinkedBlockingQueue:是一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量高于ArrayBlockingQueue
* SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移出操作,否则插入操作一直处于
* 阻塞状态,吞吐量通常要高
*
*
* 1.队列 排队打饭
* 2.阻塞队列
* 2.1阻塞队列有没有好的一面
* 2.2不得不阻塞,你如何管理
*
*
* wait notify
* */
public class BlockingQueueDemo {
public static void main(String[] args) throws Exception{
// List list = null;
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
System.out.println("-----------------------------------------------------");
zuSe();
System.out.println("-----------------------------------------------------");
addOrremove();
}
private static void zuSe() throws InterruptedException {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d");//若超出大小,则阻塞
System.out.println("==============");
blockingQueue.take();
blockingQueue.take();
blockingQueue.take();
// blockingQueue.take();
}
private static void addOrremove() {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
// 往阻塞队列添加元素
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
// 从阻塞队列取元素 队首元素是什么
System.out.println(blockingQueue.element());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
}
}
运行结果:
true
true
true
false
-----------------------------------------------------
==============
-----------------------------------------------------
true
true
true
a
a
b
c
SynchronousQueue的Demo
SynchronousQueue没有容量。
与其他BlockingQueue不同,SynchronousQueue是一个不存储元素的BlockingQueue。
每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然。
package com.neu.controller.study;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/*
* 阻塞队列SynchronousQueue演示
*
* 同步队列
* */
public class SynchronousQueueDemo {
public static void main(String[] args){
BlockingQueue<String> blockingQueue = new SynchronousQueue<>();
new Thread(()->{
try{
System.out.println(Thread.currentThread().getName()+"\t put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()+"\t put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()+"\t put 3");
blockingQueue.put("3");
} catch (InterruptedException e){
e.printStackTrace();
}
},"AAA").start();
new Thread(()->{
try{
try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e){ e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());
try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e){ e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());
try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e){ e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());
} catch (InterruptedException e){
e.printStackTrace();
}
},"BBB").start();
}
}
运行结果:
AAA put 1
BBB 1
AAA put 2
BBB 2
AAA put 3
BBB 3
以上就是队列的简单理解,可以结合代码一起看。当我们直到队列的基本理解后,我们会想到队列到底用到哪,有什么用,可见下一篇分析https://blog.csdn.net/qq_30546099/article/details/112761510。