ArrayBlockingQuque摘要
ArrayBlockingQuque
优势
- 线程同步,线程安全
- 对应空或满时,take\put操作将阻塞
- 内部是一个数组,每个元素不会产生额外的处理对象,如Node
基于什么
- ReentrantLock
- Condition
解析
构造函数
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
- 默认创建一个不公平的锁,有利于吞吐量的提高
- 基于锁创建两个条件,notEmpty\notFull,操作这两个条件的前提必须是已经获取到锁,condition.await()会释放锁进行等待直到被唤醒或中断
非阻塞添加元素 offer(X)
添加元素offer(),offer其实是非阻塞的,添加失败直接放回false
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();
}
}
/**
* Inserts element at current put position
* advances, and signals.
* Call only when holding lock.
*/
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();
}
offer方法锁定代码块,因此enqueue的操作是安全的,在enque结束后,调用
notEmpty.signal()
唤醒notEmpty.await()状态中的线程,让它退出阻塞,尝试获取锁
阻塞添加元素put
/**
* Inserts the specified element at the tail of this
* queue, waiting
* for space to become available if the queue is full.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
可以发现,如果count == items.length = true,会一直调用notFull.await()方法,释放锁,且当前线程阻塞等待,直到条件不成立,并且此处await是没有指定超时时间的,意味着它需要被其他线程唤醒
阻塞取走元素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方法先获取到锁,锁定代码块,可以看见
while (count == 0)
notEmpty.await();
它的作用是如果没有可take的元素就await,await时释放锁,当前线程陷入睡眠,当offer方法被调用,notEpty.signal()被调用后,take方法的线程从沉睡中醒来,尝试重新获取锁,此时,count == 0 = false,程序进行dequeue
/**
* Extracts element at current take position
* advances, and signals.
* Call only when holding lock.
*/
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
在获取到元素后,调用notFull.signal(),唤醒阻塞与notFull.await的线程,告诉它可以往队列里面放数据了
ArrayBlockingQuque摘要的更多相关文章
- java根据html生成摘要
转自:http://java.freesion.com/article/48772295755/ 开发一个系统,需要用到这个,根据html生成你指定多少位的摘要 package com.chendao ...
- Atitit HTTP 认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结
Atitit HTTP认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结 1.1. 最广泛使用的是基本验证 ( ...
- 2、摘要函数——MD2/MD4/MD5数字签名
摘要是用来防止数据被私自改动的方法,其中用到的函数叫做摘要函数.这些函数的输入可以是任意大小的信息,但是输出是大小固定的摘要.摘要有个重要的特性:如果改变了输入信息的任何内容,即使改变一位,输出也将发 ...
- 前端学HTTP之摘要认证
前面的话 上一篇介绍的基本认证便捷灵活,但极不安全.用户名和密码都是以明文形式传送的,也没有采取任何措施防止对报文的篡改.安全使用基本认证的唯一方式就是将其与SSL配合使用 摘要认证与基本认证兼容,但 ...
- Java 消息摘要 散列 MD5 SHA
package xxx.common.util; import java.math.BigInteger; import java.security.MessageDigest; import jav ...
- rpm查询命令摘要
任务 命令 显示软件包的相关信息 rpm -q -i NAME 列出软件包中含有的所有文件 rpm -q -i NAME 列出软件包中含有的配置文件 rpm -q -c NAME 列出软件包中含有的文 ...
- [Java 安全]消息摘要与数字签名
消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知 ...
- HMAC加密的消息摘要码
HMAC(Hash Message Authentication Code)哈希消息授权码,它在消息摘要算法(例如MD5,SHA系列算法)的基础上,使用密钥对消息摘要进行加密.它相当于一个马甲,内里可 ...
- R入门<三>-R语言实战第4章基本数据管理摘要
入门书籍:R语言实战 进度:1-4章 摘要: 1)实用的包 forecast:用于做时间序列预测的,有auto.arima函数 RODBC:可以用来读取excel文件.但据说R对csv格式适应更加良好 ...
随机推荐
- 搞 Java 的年薪 40W 是什么水平?
文章首发于[陈树义的博客],点击跳转到原文https://www.cnblogs.com/chanshuyi/p/how_to_earn_400_thousand_per_year.html 我 20 ...
- linux学习(三)Linux 系统目录结构
一.查看目录 登录系统后,在当前命令窗口下输入命令: ls / 树状目录结构: 二.目录解析 /bin: 存放二进制可执行文件(ls,cat,mkdir等). /boot: 存放启动Linux时使用的 ...
- vulnhub-Os-hackNos-2
vulnhub-Os-hackNos-2 开局扫主机,发现141是存活的,进行nmap扫描,获取端口信息. 发现22,80端口开放,进行目录爆破. 发现tsweb,浏览器访问,推测是wordpress ...
- C语言实现数据结构的邻接矩阵----数组生成矩阵、打印、深度优先遍历和广度优先遍历
写在前面 图的存储结构有两种:一种是基于二维数组的邻接矩阵表示法. 另一种是基于链表的的邻接表表示法. 在邻接矩阵中,可以如下表示顶点和边连接关系: 说明: 将顶点对应为下标,根据横纵坐标将矩阵中的某 ...
- IntelliJ IDEA 2020.2 x64 最新破解教程有效期到2089年 完全免费分享
作者:极客小俊 一个专注于web技术的80后 我不用拼过聪明人,我只需要拼过那些懒人 我就一定会超越大部分人! CSDN@极客小俊,原创文章, B站技术分享 B站视频 : Bilibili.com 个 ...
- Leetcode-数组&链表
常见双指针技巧用法,只总结思路,具体边界判定想不清楚的时候稍微画个图就行了 1. 快慢指针判断链表是否含有环.环入口(快慢指针再次相遇即有环:再从头节点和快慢指针的相遇位置同速度向后,相遇点即为环入口 ...
- 【Linux】一些文件限制配置
linux资源限制配置文件是/etc/security/limits.conf:限制用户进程的数量对于linux系统的稳定性非常重要. limits.conf文件限制着用户可以使用的最大文件数,最大线 ...
- CPU 执行程序的秘密,藏在了这 15 张图里
前言 代码写了那么多,你知道 a = 1 + 2 这条代码是怎么被 CPU 执行的吗? 软件用了那么多,你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电 ...
- java安全编码指南之:输入注入injection
目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下ja ...
- 草率了,又一个Maven打包的问题
经常遇到 Maven 相关的问题,这是之前的文章: 这个 Maven 依赖的问题,你敢说你没遇到过:https://mp.weixin.qq.com/s/SzBbDtyRUrk_7LH8SUbGXQ ...