当前位置: 首页 > 后端技术 > Java

BlockingQueue-ArrayBlockingQueue

时间:2023-04-01 16:03:58 Java

ArrayBlockingQueue比较简单。ArrayBlockingQueue是一个基于数组的阻塞队列,创建时需要指定容量,也就是说ArrayBlockingQueue是一个有界队列。ArrayBlockingQueue#Main属性项:即ArrayBlockingQueue的底层数据结构finalObject[]项;takeIndex:下一个队列的位置,包括take、poll、peek或remove等操作。putIndex:下次进入队列的位置,包括put、offer、add等操作。count:队列的实际长度。lock:ReentrantLock,进出队列时需要加锁。notEmpty:锁的条件,辅助排队线程获取数据。notFull:锁的条件,辅助加入队列的线程队列。构造方法使用非公平锁创建一个容量为capacity的队列:publicArrayBlockingQueue(intcapacity){this(capacity,false);}创建一个容量为capacity的队列,fair参数指定是使用公平锁还是非公平锁:publicArrayBlockingQueue(intcapacity,booleanfair){if(capacity<=0)thrownewIllegalArgumentException();this.items=newObject[容量];锁=新的ReentrantLock(公平);notEmpty=lock.newCondition();notFull=lock.newCondition();}创建一个非空队列。如果初始收集容量超过指定的队列容量,则会抛出异常。在初始化数据的过程中,统计队列的实际容量和putIndex:publicArrayBlockingQueue(intcapacity,booleanfair,Collectionc){this(capacity,fair);finalReentrantLocklock=this.lock;锁.锁();//锁只是为了可见性,而不是互斥try{inti=0;try{for(Ee:c){checkNotNull(e);项目[i++]=e;}}抓住(ArrayIndexOutOfBoundsExceptionex){抛出新的IllegalArgumentException();}数=我;putIndex=(i==capacity)?0:我;}最后{lock.unlock();提供put和take两种出队入队阻塞方式。非阻塞方法:add、offer、poll、peek、remove。阻塞方法put在队列满时使用notFull,take在队列空时使用notEmpty阻塞当前线程,直到满足条件才唤醒返回。非阻塞入队方法在队列未满时返回true,如果队列满则立即返回false。非阻塞dequeue方法在队列为空时立即返回null。加锁、阻塞、唤醒方法与LinkedBlockingQueue类似,代码就不贴了。而ArrayBlockingQueue的入出采用了更巧妙的算法:putIndex、takeIndex、count初始化为0,每进入一个元素,putIndex++、count++、putIndex达到队列容量item.length,然后从0开始.takeIndex的操作逻辑类似。每次出队时,takeIndex++,count--,takeIndex达到队列容量后再从0开始,每次入队都会检查队列容量是否允许当前元素入队,这样就可以了可以保证putIndex和takeIndex一直在正确的位置。两人在一条长度有限的笔直道路上,始终是同一个方向。反复循环的车子,在伯爵的配合下,两人永不相见。先简单说一下SynchronousQueue、LinkedBlockingQueue和ArrayBlockingQueue之间明显的区别或者各自的特点,不一定全面:首先,都是BlockingQueue,都是线程安全的,大家可以放心大胆的在a中使用多线程环境。SynchronousQueue是一个无界队列,队列中保存的是生产者生产的数据,或者是消费者获取数据的请求。只提供阻塞方式(底层通过transfer完成)。LinkedBlockingQueue底层是一个链表结构,可以是有界的也可以是无界的。只有生产者的数据存储在队列中。提供阻塞和非阻塞两种入队和出队操作,通过可重入锁条件阻塞线程。ArrayBlockingQueue底层是一个数组,是一个有界队列,队列中只存放生产者的数据。提供阻塞和非阻塞两种入队和出队操作,通过可重入锁的条件阻塞线程。总结分析完三个BlockingQueue的源码,就可以开始学习线程池ThreadPoolExecutor了。多谢!PreviousBlockingQueue-LinkedBlockingQueueNext线程池-ThreadPoolExecutor源码分析