阻塞队列图解
2021-10-19 10:58:42 0 举报
阻塞队列图解
作者其他创作
大纲/内容
transferForSignal(Node node):队列转移方法。该方法会先将被移除条件队列节点的status从-2更新为0(注:status是一个信号量,为-2时表示该节点在条件队列中,0是初始状态)。状态更新后会继续调用enq(final Node node)方法,enq方法是aqs中的入队方法,调用enq方法后该节点就会被添加到CLH队列,继而等待获取锁。入队后会比较该节点status的值,若status>0,则表明该节点是一个死亡节点。若该节点不是死亡节点则将status值设置为-1,表明该节点的后续结点需要被唤醒。这里若该节点是死亡节点或者status值-1设置失败,则会直接释放该节点对应线程。
new ArrayBlockingQueue(10):初始化一个数组类型的阻塞队列。该方法会初始化一个Object数组(这个数组就是队列),一个公平锁和两个条件队列。
doSignal(Node first):节点移除条件队列。该方法会将头结点移除条件队列,移除后调用transferForSignal(Node node)方法。注:该方法有while循环,但因为是单线程,所以while条件不存在treu的情况,所以只会执行一次循环体的逻辑。
enqueue(E x):入队方法。该方法会向队尾添加一个元素。如果在添加完元素之后,该队列满了,则会把添加下标置为0,也就是下次入队将会从对头开始。入队结束后会将记录元素个数的变量count加1,最后调用signal()方法。
take():获取阻塞队列中的元素。该方法会先获取锁,只有获取到锁的线程才可获取队列中的元素。获取到锁后,会继续判断当前队列的元素数量是否为0,若不为0,则获取队列中的元素(调用dequeue()获取队列中的元素),若为0则调用await方法。
signal():通知方法。该方法先会判断当前条件队列的头结点是否为空,若不为空则会调用了doSignal方法。
await():节点入条件队列方法。await方法AQS内部类ConditionObject的方法。该方法内部会调用addConditionWaiter()方法,在当前节点插入到条件队列后,将该线程阻塞。
put(E e):向阻塞队列中添加元素。该方法会先获取锁,只有获取到锁的线程才可向队列中添加元素。获取到锁后,会继续判断当前队列的元素数量和队列的长度是否相等,若不相等,则向队列中添加元素(入队调用enqueue(E x)),若相等则调用await方法。
总结:队列的生产者和消费者共用一把lock锁。当队列满时,生产者会入生产者对应的条件队列。当队列空时,消费者会入消费者对应的条件队列,这里的条件队列有两个,切勿混淆。注:条件队列的数据结构就是一个单向列表,列表中的每个节点存储了线程信息。
dequeue():出队方法。该方法会取出队列中的一个元素,元素取出后会将队列中该元素所对应的位置置为null(目的是留出空位,等待其他元素入队)。接下来会用当前取位下标比较队列长度,若下标加一等于队列长度,则说明已取到队列最后一个位置,则将取位下标置为0,下次取位则从头开始取。再下来会将记录队列元素的count值减一。最后会调用signal()方法。
addConditionWaiter():节点入条件队列方法。该方法会将当前节点插入到条件队列中
收藏
收藏
0 条评论
回复 删除
下一页