Java多线程(七)——阻塞队列

现在你已经知道了Java多线程编程的基础。但是,在实际编程过程中,你希望不要使用这种底层结构,通常,使用设计者设计好的上层结构比使用底层结构更加简单,而且安全。
很多线程问题可以使用一个或多个队列优雅而安全地解决。生产者线程向队列中插入元素,而消费者线程从队列中获取元素,队列可以让对象安全地从一个线程转移到另外一个线程。比如,考虑我们的银行转账程序。我们不直接操作对象,而是向队列中插入转账指令,另外一个线程读取转账指令,然后执行指令。只有这两个线程才有机会访问对象,我们也不需要同步。(当然,这个队列的设计者还是需要考虑线程问题的,但是你不需要)
阻塞队列会在队列满了但是你还在向里面写数据时,阻塞你的线程;在队列空了,但是你还在从里面读数据时,阻塞你的线程。阻塞队列是非常有用的工具,当两个线程分别进行读写操作时,他会自动调节两个线程的速度。它的方法主要包括:

方法正常状态特殊条件
add添加一个元素如果队列满了,抛出IllegalStateException
element返回第一个元素如果队列空,抛出NoSuchElementException
offer添加一个元素,返回true如果队列满了,返回false
peek返回第一个元素如果队列空,返回null
poll返回并删除第一个元素如果队列空,返回null
put添加一个元素如果队列满了,则阻塞
remove返回并删除第一个元素如果队列为空,抛出NoSuchElementException
take返回并删除第一个元素如果队列为空,则阻塞

根据队列为空或满了时,队列的反应,可以将方法分为三类,如果你将它用于线程控制,你应该使用put和take方法。add, remove和element会抛出异常。但是,在多线程条件下,很多情况下,队列都是空的或者满的,所以你应该使用offer, poll和peek方法,他们会使用返回值表示队列状态。
需要注意,poll和peek方法使用null表示操作失败,所以队列中不允许存在null值。
offer和poll可以接受超时参数,比如

boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);

会在100毫秒之内,尝试向队列中写入元素,如果成功,就返回true,否则返回false。类似

Object head =  q.poll(100,TimeUnit.MILLISECONDS);

在100毫秒内尝试从队列中获取元素,如果成功,返回需要的值,否则,返回null表示失败。
java.util.concurrent包提供了其他阻塞队列的变体。默认情况下,LinkedBlockingQueue没有最大的大小限制。LinkedBlockingDeque是双端队列。ArrayBlockingQueue使用给定的大小构建队列,还有一个参数表示公平。当给定公平参数时,等待时间最长的线程会被特殊对待。通常,这种公平机制会使性能得到提升,你应该仅在需要他的时候使用。
PriorityBlockingQueue是优先队列,而不是先入先出队列。队列中的元素按照优先级顺序读取。队列长度不限,但是当队列为空时,线程会被阻塞。
最终,DelayQueue包含实现了Delayed接口的对象

interface Delayed extends Comparable<Delayed>
{
	long getDelay(TimeUnit unit);
}

getDelay方法返回当前的延迟值,负值表示已经超时。只有当数据超时后,数据才能被移除。你还要实现compareTo方法,DelayQueue是用这个方法排序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值