一、前言
BlockingQueue是一个阻塞队列,而且是当下非常实用的可以解决多线程下并发问题,它是再同一时刻只有一个线程可以处理入队或者出队的容器,这样可以让程序员不用考虑多线程的逻辑,只要处理好自己的业务逻辑就可以了; 并且对于生产者和消费者场景,BlockingQueue是最好的的容器;
二、BlockingQueue队列的几个主要方法
入队:
offer(E e):如果队列没满,立即返回true; 如果队列满了,立即返回false-->不阻塞
put(E e):如果队列满了,一直阻塞,直到队列不满了或者线程被中断-->阻塞
offer(E e, long timeout, TimeUnit unit):在队尾插入一个元素,,如果队列已满,则进入等待,直到出现以下三种情况:-->阻塞
被唤醒
等待时间超时
当前线程被中断
出队:
poll():如果没有元素,直接返回null;如果有元素,出队
take():如果队列空了,一直阻塞,直到队列不为空或者线程被中断-->阻塞
poll(long timeout, TimeUnit unit):如果队列不空,出队;如果队列已空且已经超时,返回null;如果队列已空且时间未超时,则进入等待,直到出现以下三种情况:
被唤醒
等待时间超时
当前线程被中断
在Java中,BlockingQueue是一个接口,它的实现类有ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等,它们的区别主要体现在存储结构上或对元素操作上的不同,但是对于take与put操作的原理,却是类似的
再这里主要拿ArrayBlockingQueue和LinkedBlockingQueue两个队列来讲解源码;
ArrayBlockingQueue源码解析
主要几个属性:
put方法:
take方法
总结: ArrayBlockingQueue阻塞队列,首先就是判断当前队列中有元素, 如果当前元素没有满,出队线程抢到锁,然后进行入队,假如队列已满,那么这时候出队线程就会释放锁,然后进行阻塞,并且进入到条件队列中,如果下一个唤醒的还是入队线程,看到队列已然是满的就会接着还是进入到条件队列中一直阻塞,依次交替然后等到出队线程获取锁,然后进行出队消费元素,队列只要有空闲区域,那么就是来回切换通知入队线程唤醒抢锁,进行加元素,出队再次枪锁,进行出队(循环进行);
LinkedBlockingQueue源码详解
主要属性:
put 方法
take方法
总结:LinkedBlockingQueue队列,分别再出队和入队各自的锁, 都是当元素队列中为空,就从条件队列切换成加锁队列中唤醒入队线程进行添加元素,如果元素队列中不为空,那么就通知出队条件队列,有出队条件队列切换到加锁队列,然后唤醒加锁,然后进行消费元素(出队);
本人工作3年中级菜鸟程序员, 最近想回顾一下知识,做了一些简单总结同时也为了自己今后复习方便,如果有逻辑错误,大家体谅,同时也希望大牛们能给出正确答案让我改正,谢谢!