java juc包面试题_Java 经典面试题:聊一聊 JUC 下的 LinkedBlockingQueue

Java 经典面试题:聊一聊 JUC 下的 LinkedBlockingQueue

本文聊一下 JUC 下的 LinkedBlockingQueue 行列,先说说 LinkedBlockingQueue 行列的特色,然后再从源码的视点聊一聊 LinkedBlockingQueue 的首要完成~

LinkedBlockingQueue 有以下特色:

LinkedBlockingQueue 是堵塞行列,底层是单链表完成的~

元素从行列尾进队,从行列头出队,契合FIFO~

能够运用 Collection 和 Iterator 两个接口的一切操作,由于完成了两者的接口~

LinkedBlockingQueue 行列读写操作都加了锁,可是读写用的是两把不同的锁,所以能够一起读写操作~

LinkedBlockingQueue 行列承继了 AbstractQueue 类,完成了 BlockingQueue 接口,LinkedBlockingQueue 首要有以下接口:

//将指定的元素刺进到此行列的尾部(假如当即可行且不会超越该行列的容量)

//在成功时回来 true,假如此行列已满,则抛IllegalStateException。

boolean add(E e);

//将指定的元素刺进到此行列的尾部(假如当即可行且不会超越该行列的容量)

// 将指定的元素刺进此行列的尾部,假如该行列已满,

//则在抵达指定的等候时刻之前等候可用的空间,该办法可中止

boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;

//将指定的元素刺进此行列的尾部,假如该行列已满,则一向比及(堵塞)。

void put(E e) throws InterruptedException;

//获取并移除此行列的头部,假如没有元素则等候(堵塞),

//直到有元素将唤醒等候线程履行该操作

E take() throws InterruptedException;

//获取并移除此行列的头,假如此行列为空,则回来 null。

E poll();

//获取并移除此行列的头部,在指定的等候时刻前一向比及获取元素, //超越时刻办法将完毕

E poll(long timeout, TimeUnit unit) throws InterruptedException;

//从此行列中移除指定元素的单个实例(假如存在)。

boolean remove(Object o);

//获取但不移除此行列的头元素,没有则跑反常NoSuchElementException

E element();

//获取但不移除此行列的头;假如此行列为空,则回来 null。

E peek();

LinkedBlockingQueue 行列的读写办法十分的多,可是常用的是 put()、take()办法,由于它们两是堵塞的,所以咱们就从源码的视点来聊一聊 LinkedBlockingQueue 行列中这两个办法的完成。

先来看看 put()办法,源码如下:

public void put(E e) throws InterruptedException {

if (e == null) throw new NullPointerException();

// 预先设置 c 的值为 -1,表明失利

int c = -1;

Node node = new Node(e);

// 获取写锁

final ReentrantLock putLock = this.putLock;

// 获取当时行列的巨细

final AtomicInteger count = this.count;

// 设置可中止锁

putLock.lockInterruptibly();

try {

// 行列满了

// 当时线程堵塞,等候其他线程的唤醒(其他线程 take 成功后就会唤醒此处线程)

while (count.get() == capacity) {

// 无限期等候

notFull.await();

}

// 新增到行列尾部

enqueue(node);

// 获取当时的行列数

c = count.getAndIncrement();

// 假如行列未满,测验唤醒一个put的等候线程

if (c + 1 < capacity)

notFull.signal();

} finally {

// 开释锁

putLock.unlock();

}

if (c == 0)

signalNotEmpty();

}

put()办法的源码并不难,十分简略就看懂,put()办法的进程大约如下:

1、先加锁,确保容器的并发安全~

2、行列新增数据,将数据追加到行列尾部~

3、新增时,假如行列满了,当时线程是会被堵塞的,等候被唤醒~

4、新增数据成功后,在恰当机遇,会引发 put 的等候线程(行列不满时),或许 take 的等候线程(行列不为空时),这样确保行列一旦满意 put 或许 take 条件时,立马就能引发堵塞线程,持续运转,确保了引发的机遇不被糟蹋offer 就有两两种,一种是直接回来 false,另一种是超越必定时刻后回来 false~

5、开释锁~

其他的新增办法,例如 offer,能够检查源码,跟put() 办法迥然不同,相差不大~

再来看看 take()办法,源码如下:

public E take() throws InterruptedException {

E x;

// 默许负数

int c = -1;

// 当时链表的个数

final AtomicInteger count = this.count;

//获取读锁

final ReentrantLock takeLock = this.takeLock;

takeLock.lockInterruptibly();

try {

// 当行列为空时,堵塞,等候其他线程唤醒

while (count.get() == 0) {

notEmpty.await();

}

// 从行列的头部拿出一个元素

x = dequeue();

//减一操作,C比实在的行列数据大一

c = count.getAndDecrement();

// c 大于 0 ,表明行列有值,能够唤醒之前被堵塞的读线程

if (c > 1)

notEmpty.signal();

} finally {

// 开释锁

takeLock.unlock();

}

// 行列未满,能够唤醒 put 等候线程~

if (c == capacity)

signalNotFull();

return x;

}

take()办法跟 put() 办法相似,是一个相反的操作,我就不做过多的说明晰~

以上便是 LinkedBlockingQueue 行列的简略源码解析,期望对你的面试或许作业有所协助,感谢你的阅览~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值