AQS—ArrayBlockingQueue
2022-08-20 23:11:11 0 举报
ArrayBlockingQueue 入队、出队实现源码流程
作者其他创作
大纲/内容
循环唤醒所有等待队列中的线程,并添加到CLH队列中while (!transferForSignal(first) && (first = firstWaiter) != null)
true
new ArrayBlockingQueue()
2
入队ArrayBlockingQueue.offer(e)
空值校验,抛出空指针异常checkNotNull(e);
队列中没有线程等待,直接结束
释放当前线程占用的锁资源,其他线程可以进行出队操作同步代码块fullyRelease(node);
LockSupport.unpark(node.thread);
false
发送队列非空信号notEmpty是一个条件等待队列notEmpty.signal();
返回数据return x
线程到这里会被阻塞,等待被唤醒后才能继续向下执行LockSupport.park(this);
加锁失败,阻塞线程parkAndCheckInterrupt()
加锁final ReentrantLock lock = this.lock; lock.lockInterruptibly();
队列中是否有数据while (count == 0)
transferForSignal(Node node)
队列中数据长度达到最大值时添加数据失败,返回falsereturn false;
如果当前节点是头节点尝试加锁if (p == head && tryAcquire(arg)
记录当前队列大小 count++;
从队列中获取数据dequeue()
加锁成功,继续执行出队逻辑代码。(最后返回出队数据,释放锁资源,唤醒clh队列中阻塞的线程)setHead(node);p.next = null; // help GCfailed = false;return interrupted;
阻塞队列不能添加nullthrow new NullPointerException();
3
入队操作enqueue(e);
数组成环,循环取数据if (++takeIndex == items.length) takeIndex = 0;
1
span style=\"font-size: inherit;\
创建队列大小为10的阻塞队列ArrayBlockingQueue<?> xApiDataQueue = new ArrayBlockingQueue<>(10);
数组下标加1,且如果等于数组长度(队列最大长度),数组小标从头开始if (++putIndex == items.length) putIndex = 0;
将条件队列中的线程放入clh队列,Node p = enq(node);
通知当前队列为非满状态,唤醒notFull条件队列中的线程逻辑与入队操作时的notEmpty.signal();一致notFull.signal();
初始化队列底层实现数组 this.items = new Object[capacity];创建锁,默认 非公平锁 lock = new ReentrantLock(fair);非空条件等待队列 notEmpty = lock.newCondition();非满条件等待对硫磷 notFull = lock.newCondition();
阻塞,等待上一个线程退出后唤醒LockSupport.park(this);
出队ArrayBlockingQueue.take()
4.return x;
拿到提条件等待队列头指针 Node first = firstWaiter;
if (first != null)
发送唤醒线程信号doSignal(first);
拿到真正保存数据的数组该阻塞队列是基于数组实现的final Object[] items = this.items;
加锁,阻塞队列是线程安全的final ReentrantLock lock = this.lock; lock.lock();
取出底层实现数组中的数据E x = (E) items[takeIndex];
notEmpty.await();
数据放入数组items[putIndex] = x;
解锁,释放锁资源finally { lock.unlock();}
false队列中没有数据
解锁,释放资源lock.unlock();
线程唤醒
count == items.length
数据添加成功return true;
将当前线程封装成一个Node放入notEmpty中的条件等待队列中Node node = addConditionWaiter();
拿到当前节点的上一个节点final Node p = node.predecessor();
0 条评论
回复 删除
下一页