blockingqueue java_【死磕Java并发】-J.U.C之阻塞队列:ArrayBlockingQueue - Java 技术驿站-Java 技术驿站...

ArrayBlockingQueue,一个由数组实现的有界阻塞队列。该队列采用FIFO的原则对元素进行排序添加的。

ArrayBlockingQueue为有界且固定,其大小在构造时由构造函数来决定,确认之后就不能再改变了。ArrayBlockingQueue支持对等待的生产者线程和使用者线程进行排序的可选公平策略,但是在默认情况下不保证线程公平的访问,在构造时可以选择公平策略(fair = true)。公平性通常会降低吞吐量,但是减少了可变性和避免了“不平衡性”。

ArrayBlockingQueue

先看ArrayBlockingQueue的定义:

public class ArrayBlockingQueue extends AbstractQueue implements BlockingQueue, Serializable {

private static final long serialVersionUID = -817911632652898426L;

final Object[] items;

int takeIndex;

int putIndex;

int count;

// 重入锁

final ReentrantLock lock;

// notEmpty condition

private final Condition notEmpty;

// notFull condition

private final Condition notFull;

transient ArrayBlockingQueue.Itrs itrs;

}

可以清楚地看到ArrayBlockingQueue继承AbstractQueue,实现BlockingQueue接口。看过java.util包源码的同学应该都认识AbstractQueue,改类在Queue接口中扮演着非常重要的作用,该类提供了对queue操作的骨干实现(具体内容移驾其源码)。BlockingQueue继承java.util.Queue为阻塞队列的核心接口,提供了在多线程环境下的出列、入列操作,作为使用者,则不需要关心队列在什么时候阻塞线程,什么时候唤醒线程,所有一切均由BlockingQueue来完成。

ArrayBlockingQueue内部使用可重入锁ReentrantLock + Condition来完成多线程环境的并发操作。

items,一个定长数组,维护ArrayBlockingQueue的元素

takeIndex,int,为ArrayBlockingQueue对首位置

putIndex,int,ArrayBlockingQueue对尾位置

count,元素个数

lock,锁,ArrayBlockingQueue出列入列都必须获取该锁,两个步骤公用一个锁

notEmpty,出列条件

notFull,入列条件

入队

ArrayBlockingQueue提供了诸多方法,可以将元素加入队列尾部。

add(E e) :将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量),在成功时返回 true,如果此队列已满,则抛出 IllegalStateException

offer(E e) :将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量),在成功时返回 true,如果此队列已满,则返回 false

offer(E e, long timeout, TimeUnit unit) :将指定的元素插入此队列的尾部,如果该队列已满,则在到达指定的等待时间之前等待可用的空间

put(E e) :将指定的元素插入此队列的尾部,如果该队列已满,则等待可用的空间

方法较多,我们就分析一个方法:add(E e):

public boolean add(E e) {

return super.add(e);

}

public boolean add(E e) {

if (offer(e))

return true;

else

throw new IllegalStateException("Queue full");

}

add方法调用offer(E e),如果返回false,则直接抛出IllegalStateException异常。offer(E e)为ArrayBlockingQueue实现:

public boolean offer(E e) {

checkNotNull(e);

final ReentrantLock lock = this.lock;

lock.lock();

try {

if (count == items.length)

return false;

else {

enqueue(e);

return true;

}

} finally {

lock.unlock();

}

}

方法首先检查是否为null,然后获取lock锁。获取锁成功后,如果队列已满则直接返回false,否则调用enqueue(E e),enqueue(E e)为入列的核心方法,所有入列的方法最终都将调用该方法在队列尾部插入元素:

private void enqueue(E x) {

// assert lock.getHoldCount() == 1;

// assert items[putIndex] == null;

final Object[] items = this.items;

items[putIndex] = x;

if (++putIndex == items.length)

putIndex = 0;

count++;

notEmpty.signal();

}

该方法就是在putIndex(对尾)为知处添加元素,最后使用notEmpty的signal()方法通知阻塞在出列的线程(如果队列为空,则进行出列操作是会阻塞)。

出队

ArrayBlockingQueue提供的出队方法如下:

poll() :获取并移除此队列的头,如果此队列为空,则返回 null

poll(long timeout, TimeUnit unit) :获取并移除此队列的头部,在指定的等待时间前等待可用的元素(如果有必要)

remove(Object o) :从此队列中移除指定元素的单个实例(如果存在)

take() :获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)

poll()

public E poll() {

final ReentrantLock lock = this.lock;

lock.lock();

try {

return (count == 0) ? null : dequeue();

} finally {

lock.unlock();

}

}

如果队列为空返回null,否则调用dequeue()获取列头元素:

private E dequeue() {

final Object[] items = this.items;

E x = (E) items[takeIndex];

items[takeIndex] = null;

if (++takeIndex == items.length)

takeIndex = 0;

count--;

if (itrs != null)

itrs.elementDequeued();

notFull.signal();

return x;

}

该方法主要是从列头(takeIndex 位置)取出元素,同时如果迭代器itrs不为null,则需要维护下该迭代器。最后调用notFull.signal()唤醒入列线程。

take()

public E take() throws InterruptedException {

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

while (count == 0)

notEmpty.await();

return dequeue();

} finally {

lock.unlock();

}

}

take()与poll()存在一个区别就是count == 0 时的处理,poll()直接返回null,而take()则是在notEmpty上面等待直到被入列的线程唤醒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
毕业设计,基于SpringBoot+Vue+MySQL开发的社区医院管理系统,源码+数据库+毕业论文+视频演示 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的社区医院管理系统实现了病例信息、字典表、家庭医生、健康档案、就诊信息、前台、药品、用户、用户、用户表等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让社区医院管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。 关键字:社区医院管理系统;信息管理,时效性,安全性,MySql
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值