Java特性队列和栈的堵塞原理解析
做消息通信,消息会不断从网络流中取得,而后台也有线程不断消费。本来我一直是使用一些线程安全标识或方法来控制,后来在网上找到一些java新特性,里面包含了可以用到的堆栈使用,而且是堵塞的,这样至少可以保证一些安全性。
对于堆:
BlockingQueue不接受null元素。试图add、put或offer一个null元素时,某些实现会抛出NullPointerException。null被用作指示poll操作失败的警戒值。
BlockingQueue可以是限定容量的。它在任意给定时间都可以有一个remainingCapacity,超出此容量,便无法无阻塞地put附加元素。没有任何内部容量约束的BlockingQueue总是报告Integer.MAX_VALUE的剩余容量。
BlockingQueue实现主要用于生产者-使用者队列,但它另外还支持Collection接口。因此,举例来说,使用remove(x)从队列中移除任意一个元素是有可能的。然而,这种操作通常不会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。
BlockingQueue实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的Collection操作(addAll、containsAll、retainAll和removeAll)没有必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了c中的一些元素后,addAll(c)有可能失败(抛出一个异常)。
看一段代码:
packagecom.test; importjava.util.concurrent.ArrayBlockingQueue; importjava.util.concurrent.BlockingQueue; /** *@说明堵塞队列和栈的使用 */ publicclassTest{ @SuppressWarnings("unchecked") publicstaticvoidmain(String[]args)throwsInterruptedException{ BlockingQueuebqueue=newArrayBlockingQueue(5); for(inti=0;i<10;i++){ //添加元素到队列,如果没有可用空间,将一直等待(如果有必要) bqueue.put(i); System.out.println("添加了元素:"+i); } System.out.println("----End----"); } }
运行效果:
添加了元素:0
添加了元素:1
添加了元素:2
添加了元素:3
添加了元素:4
之后就会一直等待。
对于栈:
BlockingDeque方法有四种形式,使用不同的方式处理无法立即满足但在将来某一时刻可能满足的操作:第一种方式抛出异常;第二种返回一个特殊值(null或false,具体取决于操作);第三种无限期阻塞当前线程,直至操作成功;第四种只阻塞给定的最大时间,然后放弃。
看一个例子:
packagecom.test; importjava.util.concurrent.BlockingDeque; importjava.util.concurrent.LinkedBlockingDeque; /** *@说明堵塞队列和栈的使用 */ publicclassTest{ @SuppressWarnings("unchecked") publicstaticvoidmain(String[]args)throwsInterruptedException{ BlockingDequebDeque=newLinkedBlockingDeque(5); for(inti=0;i<10;i++){ //将指定元素添加到此阻塞栈中,如果没有可用空间,将一直等待(如果有必要)。 bDeque.putFirst(i); System.out.println("添加了元素:"+i); } System.out.println("----End----"); } }
运行结果和堆一样,也会产生等待。
对于两者的解释:
阻塞队列的概念是,一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止。同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元素为止。
对于阻塞栈,与阻塞队列相似。不同点在于栈是“后入先出”的结构,每次操作的是栈顶,而队列是“先进先出”的结构,每次操作的是队列头。
注意的是,BlockingQueue是5中的特性,jdk6以后才增加了BlockingDeque。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。