ArrayBlockingQuque

优势

  1. 线程同步,线程安全
  2. 对应空或满时,take\put操作将阻塞
  3. 内部是一个数组,每个元素不会产生额外的处理对象,如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摘要的更多相关文章

  1. java根据html生成摘要

    转自:http://java.freesion.com/article/48772295755/ 开发一个系统,需要用到这个,根据html生成你指定多少位的摘要 package com.chendao ...

  2. Atitit HTTP 认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结

    Atitit HTTP认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结 1.1. 最广泛使用的是基本验证 ( ...

  3. 2、摘要函数——MD2/MD4/MD5数字签名

    摘要是用来防止数据被私自改动的方法,其中用到的函数叫做摘要函数.这些函数的输入可以是任意大小的信息,但是输出是大小固定的摘要.摘要有个重要的特性:如果改变了输入信息的任何内容,即使改变一位,输出也将发 ...

  4. 前端学HTTP之摘要认证

    前面的话 上一篇介绍的基本认证便捷灵活,但极不安全.用户名和密码都是以明文形式传送的,也没有采取任何措施防止对报文的篡改.安全使用基本认证的唯一方式就是将其与SSL配合使用 摘要认证与基本认证兼容,但 ...

  5. Java 消息摘要 散列 MD5 SHA

    package xxx.common.util; import java.math.BigInteger; import java.security.MessageDigest; import jav ...

  6. rpm查询命令摘要

    任务 命令 显示软件包的相关信息 rpm -q -i NAME 列出软件包中含有的所有文件 rpm -q -i NAME 列出软件包中含有的配置文件 rpm -q -c NAME 列出软件包中含有的文 ...

  7. [Java 安全]消息摘要与数字签名

    消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知 ...

  8. HMAC加密的消息摘要码

    HMAC(Hash Message Authentication Code)哈希消息授权码,它在消息摘要算法(例如MD5,SHA系列算法)的基础上,使用密钥对消息摘要进行加密.它相当于一个马甲,内里可 ...

  9. R入门<三>-R语言实战第4章基本数据管理摘要

    入门书籍:R语言实战 进度:1-4章 摘要: 1)实用的包 forecast:用于做时间序列预测的,有auto.arima函数 RODBC:可以用来读取excel文件.但据说R对csv格式适应更加良好 ...

随机推荐

  1. 搞 Java 的年薪 40W 是什么水平?

    文章首发于[陈树义的博客],点击跳转到原文https://www.cnblogs.com/chanshuyi/p/how_to_earn_400_thousand_per_year.html 我 20 ...

  2. linux学习(三)Linux 系统目录结构

    一.查看目录 登录系统后,在当前命令窗口下输入命令: ls / 树状目录结构: 二.目录解析 /bin: 存放二进制可执行文件(ls,cat,mkdir等). /boot: 存放启动Linux时使用的 ...

  3. vulnhub-Os-hackNos-2

    vulnhub-Os-hackNos-2 开局扫主机,发现141是存活的,进行nmap扫描,获取端口信息. 发现22,80端口开放,进行目录爆破. 发现tsweb,浏览器访问,推测是wordpress ...

  4. C语言实现数据结构的邻接矩阵----数组生成矩阵、打印、深度优先遍历和广度优先遍历

    写在前面 图的存储结构有两种:一种是基于二维数组的邻接矩阵表示法. 另一种是基于链表的的邻接表表示法. 在邻接矩阵中,可以如下表示顶点和边连接关系: 说明: 将顶点对应为下标,根据横纵坐标将矩阵中的某 ...

  5. IntelliJ IDEA 2020.2 x64 最新破解教程有效期到2089年 完全免费分享

    作者:极客小俊 一个专注于web技术的80后 我不用拼过聪明人,我只需要拼过那些懒人 我就一定会超越大部分人! CSDN@极客小俊,原创文章, B站技术分享 B站视频 : Bilibili.com 个 ...

  6. Leetcode-数组&链表

    常见双指针技巧用法,只总结思路,具体边界判定想不清楚的时候稍微画个图就行了 1. 快慢指针判断链表是否含有环.环入口(快慢指针再次相遇即有环:再从头节点和快慢指针的相遇位置同速度向后,相遇点即为环入口 ...

  7. 【Linux】一些文件限制配置

    linux资源限制配置文件是/etc/security/limits.conf:限制用户进程的数量对于linux系统的稳定性非常重要. limits.conf文件限制着用户可以使用的最大文件数,最大线 ...

  8. CPU 执行程序的秘密,藏在了这 15 张图里

    前言 代码写了那么多,你知道 a = 1 + 2 这条代码是怎么被 CPU 执行的吗? 软件用了那么多,你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电 ...

  9. java安全编码指南之:输入注入injection

    目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下ja ...

  10. 草率了,又一个Maven打包的问题

    经常遇到 Maven 相关的问题,这是之前的文章: 这个 Maven 依赖的问题,你敢说你没遇到过:https://mp.weixin.qq.com/s/SzBbDtyRUrk_7LH8SUbGXQ ...