2024年安卓最全ArrayBlockingQueue源码解析(JDK1,头条面试题

写在最后

由于本文罗列的知识点是根据我自身总结出来的,并且由于本人水平有限,无法全部提及,欢迎大神们能补充~

将来我会对上面的知识点一个一个深入学习,也希望有童鞋跟我一起学习,一起进阶。

提升架构认知不是一蹴而就的,它离不开刻意学习和思考。

**这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家,**梳理了多年的架构经验,筹备近1个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

最近还在整理并复习一些Android基础知识点,有问题希望大家够指出,谢谢。

希望读到这的您能转发分享和关注一下我,以后还会更新技术干货,谢谢您的支持!

转发+点赞+关注,第一时间获取最新知识点

Android架构师之路很漫长,一起共勉吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

public ArrayBlockingQueue(int capacity) {

this(capacity, false);

}

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();

}

public ArrayBlockingQueue(int capacity, boolean fair,

Collection<? extends E> c) {

this(capacity, fair);

final ReentrantLock lock = this.lock;

lock.lock(); // Lock only for visibility, not mutual exclusion

try {

int i = 0;

try {

for (E e : c) {

checkNotNull(e);

items[i++] = e;

}

} catch (ArrayIndexOutOfBoundsException ex) {

throw new IllegalArgumentException();

}

count = i;

putIndex = (i == capacity) ? 0 : i;

} finally {

lock.unlock();

}

}

从三个构造方法中可以看出主要是capacity、fair这两个的不同参数

capacity:设置容量,必传值

fair:是否公平,默认值为false,是设置ReentrantLock是公平锁还是非公平锁的

预备知识

ReentrantLock是一个支持响应中断、超时、尝试获取锁,可关联多个条件队列,是个可重入的公平锁和非公平锁。

Condition这个主要是用来实现ReentrantLock的wait和notify的功能

增删改查


入队操作

public void put(E e) throws InterruptedException {

//检验元素是否为空,为null就抛出空指针异常

checkNotNull(e);

//拿到当前的锁

final ReentrantLock lock = this.lock;

//进行锁的抢占

lock.lockInterruptibly();

try {

//当队列长度等于数组长度,表示队列已满,这里使用while来循环等待被唤醒

while (count == items.length)

//put操作时让当前线程处于等待状态

notFull.await();

//当队列没有满并且获取到锁时就进行enqueue入队操作

enqueue(e);

} finally {

//完成锁的释放

lock.unlock();

}

}

private static void checkNotNull(Object v) {

if (v == null)

throw new NullPointerException();

}

private void enqueue(E x) {

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

// assert items[putIndex] == null;

final Object[] items = this.items;

//设置当前数组putIndex位置的元素为x,这里是尾部插入

items[putIndex] = x;

//putIndex++,然后如果putIndex的大小等于数据的长度,则设置putIndex=0,这里是循环队列的思想

if (++putIndex == items.length)

putIndex = 0;

//元素的个数+1

count++;

//put操作结束,唤醒其他正在处于等待状态的线程

notEmpty.signal();

}

另外offer()函数也可以入队,思路也差不多,也可以了解一下,总结一下入队操作,先检查,然后判断队列没有满并且拿到锁进行入队操作进行设置数组相关位置的值,设置完成,唤醒其他处于等待状态的线程

删除元素

remove()具体元素的出队

public boolean remove(Object o) {

//出队的元素为null,直接返回失败

if (o == null) return false;

//得到数据

final Object[] items = this.items;

//拿到锁

final ReentrantLock lock = this.lock;

//进行锁住操作

lock.lock();

try {

if (count > 0) {

final int putIndex = this.putIndex;

int i = takeIndex;

//循环查找i位置的数据释放就是要删除出队的数据,如果是就进行删除

do {

if (o.equals(items[i])) {

removeAt(i);

return true;

}

if (++i == items.length)

i = 0;

} while (i != putIndex);

}

//元素个数没有大于0直接返回失败

return false;

} finally {

//锁的释放

lock.unlock();

}

}

void removeAt(final int removeIndex) {

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

// assert items[removeIndex] != null;

// assert removeIndex >= 0 && removeIndex < items.length;

final Object[] items = this.items;

//待删除的下标等于读取的下标

if (removeIndex == takeIndex) {

// removing front item; just advance

//设置数组对应下标的值为null

items[takeIndex] = null;

if (++takeIndex == items.length)

takeIndex = 0;

//元素的个数-1

count–;

//通知所有迭代器头节点出队

if (itrs != null)

itrs.elementDequeued();

} else {

// an “interior” remove

// slide over all others up through putIndex.

final int putIndex = this.putIndex;

//从待删除的下标开始循环查找并设置数据i位置的数据

for (int i = removeIndex;😉 {

int next = i + 1;

if (next == items.length)

next = 0;

if (next != putIndex) {

items[i] = items[next];

i = next;

} else {

items[i] = null;

this.putIndex = i;

break;

}

}

count–;

//通过所有迭代器有内部节点出队

if (itrs != null)

itrs.removedAt(removeIndex);

}

//唤醒其他等待的线程

notFull.signal();

}

take()是队列头数据出队,poll()方法也是一样的

public E take() throws InterruptedException {

final ReentrantLock lock = this.lock;

//尝试去获取锁,如果锁被其他线程占用,那么当前线程就属于等待状态

lock.lockInterruptibly();

try {

//如果元素个数为0,就让当前线程等待,并且释放锁

while (count == 0)

notEmpty.await();

//如果队列不为空,则进行出队,从队列头部取元素

最后

以前一直是自己在网上东平西凑的找,找到的东西也是零零散散,很多时候都是看着看着就没了,时间浪费了,问题却还没得到解决,很让人抓狂。

后面我就自己整理了一套资料,还别说,真香!

资料有条理,有系统,还很全面,我不方便直接放出来,大家可以先看看有没有用得到的地方吧。

系列教程图片

2020Android复习资料汇总.png

flutter

NDK

设计思想开源框架

微信小程序

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

[外链图片转存中…(img-enEMq0Dk-1715745740215)]

[外链图片转存中…(img-bJ6DoZGQ-1715745740215)]

[外链图片转存中…(img-bXHBzll4-1715745740216)]

[外链图片转存中…(img-NyzeOhH4-1715745740217)]

[外链图片转存中…(img-LqQ2Lz6c-1715745740217)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值