2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Java并发编程-BlockingQueue阻塞队列

Java并发编程-BlockingQueue阻塞队列

时间:2019-04-06 08:14:23

相关推荐

Java并发编程-BlockingQueue阻塞队列

BlockingQueue阻塞队列

1.BlockingQueue介绍1.1.引言:1.2.阻塞队列介绍:1.3.阻塞队列的用处:1.4.接口架构图2.BlockingQueue核心方法3.BlockingQueue案例测试3.1.抛出异常的方法代码验证:3.2.返回特殊值的方法(boolean值返回)3.3.阻塞队列的方法3.4.超时中断的方法

1.BlockingQueue介绍

1.1.引言:

阻塞虽然是不好的,但是我们有时候不得不阻塞,比如说一家餐厅人满了,店主当然不希望即将过来的这些客人全部都走,而是希望它们留下来继续排队等候。对于阻塞的内容,线程和资源的调度管理能力,这样就出了一个接口,就叫阻塞队列。在不得不阻塞,必须要阻塞的时候,如何管理好被阻塞的资源和线程,这就是阻塞队列。

队列的特性:先进先出,插入元素在队尾,删除元素在队头。

1.2.阻塞队列介绍:

阻塞:必须要阻塞/不得不阻塞

阻塞队列是一个队列,在数据结构中中起的作用如下图:

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

阻塞队列,我们可以简单的理解为海底捞火锅店的候客区,如图绿框框就是我们的阻塞队列,即我们所理解的海底捞火锅店的候客区,里面等着的就是一桌一桌的食客。如果候客区也满了,还加不加人?

当队列是空的,从队列中获取元素的操作将会被阻塞。

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

试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素。

对于上面阻塞的问题,我们又可以举一个例子,假如说Thread1是做蛋糕的师傅,Thread2是买蛋糕的顾客,而BlockingQueue是食品柜。当顾客来了,发现食品柜是空的,想消费蛋糕的操作将会被阻塞。如果蛋糕买的人少了,食品柜中的蛋糕满了,此时生产蛋糕的操作将会被阻塞。

**试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素。**简单的说,就是空的时候不能消费,满的时候不能增加。

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

1.3.阻塞队列的用处:

在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起。

wait就是一种阻塞,notify是一种唤醒,await是一种阻塞, signal是唤醒。

为什么需要 BlockingQueue?

好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue 都给你一手包办了。在 concurrent 包发布以前,在多线程环境下,我们每个程序员都必须自己去控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。

也就是不用手写wait和notify了。只要柜子里蛋糕满了,生产线程就会阻塞,只要柜子里没有蛋糕了,消费线程就会被阻塞。

1.4.接口架构图

BlockingQueue所有已知实现类:

ArrayBlockingQueue ,DelayQueue ,LinkedBlockingDeque, LinkedBlockingQueue , LinkedTransferQueue , PriorityBlockingQueue , SynchronousQueue

在我们以前学习集合的过程中,Collection接口有两个常用的接口List接口和Set接口,现在又有了阻塞队列接口BlockingQueue

ArrayBlockingQueue:由数组结构组成的有界阻塞队列

LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为integer.MAX_VALUE)阻塞队列

PriorityBlockingQueue:支持优先级排序的无界阻塞队列

DelayQueue:使用优先级队列实现的延迟无界阻塞队列

SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列

LinkedTransferQueue:由链表结构组成的无界阻塞队列

LinkedBlockingDeque:由链表结构组成的双向阻塞队列

2.BlockingQueue核心方法

核心方法如下:

共同点:插入成功或者删除成功都返回true(除了put和take),区别在于处理异常情况

(1)抛出异常的方法

当阻塞队列满时,再往队列里add元素会抛出IllegalStateException:Queue full;

当阻塞队列空时,再从队列里remove移除元素会抛NoSuchElementException。

(2)返回特殊值(boolean值)的方法

插入成功,返回true;插入失败,返回false;

删除成功返回出队列元素;删除失败返回null;

(3)阻塞的方法(添加无返回值)

当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据or响应中断退出。

当阻塞队列空时,消费者线程试图take队列里的元素,队列会一直阻塞消费者线程直到队列有可用元素。

(4)超时的方法

当向阻塞队列offer元素时候,时间超过了设定的值,就会出现超时中断;

当向阻塞队列poll元素时候,时间超过了设定的值,就会出现超时中断。

3.BlockingQueue案例测试

3.1.抛出异常的方法代码验证:

add方法抛出异常

public static void main(String[] args) {//ArrayBlockingQueue是由数组结构组成的有界阻塞队列,所以要加参数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.add("d"));}

public static void main(String[] args) {//ArrayBlockingQueue是由数组结构组成的有界阻塞队列,所以要加参数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.add("d"));}

当阻塞队列满时,再往队列里add元素会抛出IllegalStateException:Queue full;

remove方法抛出异常

public static void main(String[] args) {//ArrayBlockingQueue是由数组结构组成的有界阻塞队列,所以要加参数BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.add("a"));System.out.println(blockingQueue.add("b"));System.out.println(blockingQueue.add("c"));//remove会返回被移除的对象System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());}

当阻塞队列空时,再从队列里remove移除元素会抛NoSuchElementException。

element检查方法:(底层调用了 peek()方法)

public static void main(String[] args) {//ArrayBlockingQueue是由数组结构组成的有界阻塞队列,所以要加参数BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.add("a"));System.out.println(blockingQueue.add("a"));//element就是查看一下队首元素的值System.out.println(blockingQueue.element());}

3.2.返回特殊值的方法(boolean值返回)

阻塞队列offer方法的使用

public static void main(String[] args) {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("a"));System.out.println(blockingQueue.offer("b"));System.out.println(blockingQueue.offer("c"));System.out.println(blockingQueue.offer("d"));}

插入成功,返回true;插入失败,返回false;

阻塞队列poll方法的使用

public static void main(String[] args) {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("a"));System.out.println(blockingQueue.offer("b"));System.out.println(blockingQueue.offer("c"));System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());}

删除成功返回出队列元素;删除失败返回null;

3.3.阻塞队列的方法

阻塞队列put方法使用

public static void main(String[] args) throws InterruptedException {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);blockingQueue.put("a");blockingQueue.put("a");blockingQueue.put("a");blockingQueue.put("a");}

没有报错,当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据or响应中断退出。,即腾出空位置为止,能塞进去。与semaphore争车位类似

阻塞队列take方法使用

public static void main(String[] args) throws InterruptedException {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);blockingQueue.put("a");blockingQueue.put("a");blockingQueue.put("a");System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());}

当阻塞队列空时,消费者线程试图take队列里的元素,队列会一直阻塞消费者线程直到队列有可用元素。

3.4.超时中断的方法

阻塞队列offer超时中断演示

public static void main(String[] args) throws InterruptedException {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));}

程序执行结果如下:当往阻塞队列添加第六个元素的时候,队列添加不进去,3秒后会超时中断。

当向阻塞队列offer元素时候,时间超过了设定的值,就会出现超时中断;

阻塞队列poll超时中断演示

public static void main(String[] args) throws InterruptedException {BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.offer("a",3L,TimeUnit.SECONDS));System.out.println(blockingQueue.poll(3L,TimeUnit.SECONDS));System.out.println(blockingQueue.poll(3L,TimeUnit.SECONDS));System.out.println(blockingQueue.poll(3L,TimeUnit.SECONDS));System.out.println(blockingQueue.poll(3L,TimeUnit.SECONDS));}

当向阻塞队列poll元素时候,时间超过了设定的值,就会出现超时中断。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。