(13)多线程与并发库之java5阻塞队列的应用

首先复习一下:

1,内部类的实例方法不能在静态中创建。

2,成员变量 在什么情况情况下才有值啊?在创建了类的实例对象的时候,才分配空间。这时,就需要一个构造方法来进行赋值。

3,static{


}这种语法,不需要创建实例对象 就可以运行,而bq1,bq2 是对象创建后的成员变量,对象里面的变量,所以不可应用静态代码块。

要用 这种匿名构造方法{ } 它的运行时机 在任何构造方法之前,只要调用 构造方法,匿名构造方法都会执行,也就是说 创建了几个对象,匿名构造方法就会执行几次。

而 静态代码块 是在 类加载的时候 执行。且 只调用一次。


分析:首先开启两个线程,

第一轮:queue1 刚开始为空的,所以它就想放入(put)数据。

而queue2刚开始为满的,这时他也想放入(put)数据,所以queue2就堵塞在那里了。

第二轮:1线程的queue2这时取出(take)数据,哈哈,这时 2 线程上的queue2就可以走了。

如图:

(13)多线程与并发库之java5阻塞队列的应用


说明:阻塞对列和Semaphore有些类似,但也不同,阻塞队列是一方存数据,另一方取数据。而Semaphire通常是由同一方设置和释放信号量。

java.util.concurrent
接口 BlockingQueue<E>

类型参数:
E - 在此 collection 中保持的元素类型
所有超级接口:
Collection<E>, Iterable<E>, Queue<E>
所有已知子接口:
BlockingDeque<E>
所有已知实现类:
ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue

public interface BlockingQueue<E>
extends Queue<E>
 

支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(nullfalse,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查 element() peek() 不可用 不可用

BlockingQueue 不接受 null 元素。试图 addputoffer 一个 null 元素时,某些实现会抛出 NullPointerExceptionnull 被用作指示poll 操作失败的警戒值。

【1】BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个 remainingCapacity,超出此容量,便无法无阻塞地put 附加元素。没有任何内部容量约束的BlockingQueue 总是报告 Integer.MAX_VALUE 的剩余容量。

【2】BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持 Collection 接口。因此,举例来说,使用 remove(x) 从队列中移除任意一个元素是有可能的。然而,这种操作通常 会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。

【3】BlockingQueue 实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的 Collection 操作(addAllcontainsAllretainAllremoveAll没有 必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了c 中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。

【4】BlockingQueue 实质上 支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。这种功能的需求和使用有依赖于实现的倾向。例如,一种常用的策略是:对于生产者,插入特殊的end-of-streampoison 对象,并根据使用者获取这些对象的时间来对它们进行解释。

以下是基于典型的生产者-使用者场景的一个用例。注意,BlockingQueue 可以安全地与多个生产者和多个使用者一起使用。


内存一致性效果:当存在其他并发 collection 时,将对象放入 BlockingQueue 之前的线程中的操作 happen-before 随后通过另一线程从 BlockingQueue 中访问或移除该元素的操作。


示例代码:


运行结果:

死锁。

原因:没有把synchronized 关键字 去掉,所以造成了死锁。





你可能感兴趣的:(java)