【多线程学习】阻塞队列BlockingQueue

「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

阻塞队列

队列就是类似这种爬管道先进去的先出来

image.png

多线程中,通过队列实现线程之间的数据共享,就像之前的生产者消费者模式,通过队列可以很便利地实现两者之间的数据共享。在正常情况下大家都你生产我拿走大家都其乐融融,但是生活总是没有那么美好,时不时会来一点小意外,生产者和消费者在某个时间段内,发生数据处理速度不匹配的情况,就会出现不得不阻塞的情况

  1. 队列中的位置都满员了,新来的就挤不进去没有位置不得不等待前面进去的被拿出来

  2. 队列中没有东西了,想要拿出但是拿不出,不得不的等待生产东西进去才能拿

List集合和Set集合这些的祖宗都是Collection,查看Collection的实现类发现BlockingQueue也是在Collection下面的,而且还是和List,Set同级的

image.png

什么情况下会使用到阻塞队列:多线程并发处理,线程池

BlockingQueue 的API

方式 抛出异常 有返回值,不抛出异常 阻塞等待 超时等待
添加 add offer put offer(数据,超时时间,时间单位)
移除 remove poll take poll(等待时间,时间单位)
检测列首数据 element peek

demo实现

抛出异常的方式

首先定义队列的大小为3,代表只能像队列里面添加三个元素,移除三个元素。先测试一下正常情况,添加三个元素,移除三个元素。使用 add 和 remove 分别去添加和移除数据

image.png
运行程序查看结果
image.png

正常方式的结果都在我们的意料之中,在修改一下程序,像容量只有3的队列添加4个数据,或者添加3个数据但是移除4个,运行测试程序看会出现什么结果

当添加4个数据时抛出异常: java.lang.IllegalStateException: Queue full 队列已经满,当添加3个数据移除4个数据时,抛出异常 java.util.NoSuchElementException没有数据了

有返回值,不抛出异常的方式

在添加数据或者移除数据出错时,不抛出异常当队列满了之后不去抛出异常告诉我是否添加成功就可以了。使用offer和poll分别去添加和移除数据

image.png

运行程序发现,在添加超容量时,继续添加数据,添加不成功的时候返回了一个fasle并没有抛出异常,在已经没有元素的时候还去取数据,也不会抛出异常而是返回一个null

image.png

等待,阻塞方式 (一直等待)

超出容量了还在往里面添加数据,队列没有位置了就会一直等待,队列中已经没有数据了也会一直等待,不会抛出异常也没有返回值,使用 put和take来添加和取出元素

image.png

查看运行结果,会发现控制台程序运行会一直不结束一直等待着

image.png

等待,阻塞方式 (超时退出)

和第三个阻塞方式不同的是,等过了设置的等待时间就不会等了,继续往下了,测试超出容量了还在往里面添加数据,队列没有位置了阻塞超过了等待时间就不等了,队列中已经没有数据了也只会等待设置的时间之后就不在等待,不会抛出异常也有返回值,使用 offer(数据,超时时间,时间单位)和poll(等待时间,时间单位)来添加和取出元素

image.png

查看运行结果,效果静态的图片看不出来效果,自己运行程序的时候就能看到等待时间的那个等待间隔

image.png