您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Java中常用阻塞隊(duì)列的問(wèn)題是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Java中常用阻塞隊(duì)列的問(wèn)題是什么”吧!
內(nèi)部由一個(gè)固定長(zhǎng)度的數(shù)組來(lái)實(shí)現(xiàn)阻塞隊(duì)列
/** The queued items */ final Object[] items; /** items index for next take, poll, peek or remove */ int takeIndex; /** items index for next put, offer, or add */ int putIndex; public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); /** 定長(zhǎng)數(shù)組 */ this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }
提供了兩個(gè)入隊(duì)操作方法,offer()和put()
offer方法不會(huì)阻塞,但有返回值,如果隊(duì)列滿(mǎn)了,那么直接返回false,否則插入數(shù)據(jù)并返回true。
/** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, * returning {@code true} upon success and {@code false} if this queue * is full. This method is generally preferable to method {@link #add}, * which can fail to insert an element only by throwing an exception. * * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { enqueue(e); return true; } } finally { lock.unlock(); } }
put()會(huì)在隊(duì)列滿(mǎn)了的時(shí)候會(huì)阻塞生產(chǎn)者線(xiàn)程,知道有消費(fèi)者線(xiàn)程消費(fèi)后將其喚醒。
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } } private E dequeue() { // assert lock.getHoldCount() == 1; // assert items[takeIndex] != null; final Object[] items = this.items; @SuppressWarnings("unchecked") E x = (E) items[takeIndex]; items[takeIndex] = null; if (++takeIndex == items.length) takeIndex = 0; count--; if (itrs != null) itrs.elementDequeued(); notFull.signal(); // 出隊(duì)后喚醒生產(chǎn)者線(xiàn)程 return x; }
基于鏈表的阻塞隊(duì)列,同ArrayListBlockingQueue類(lèi)似,其內(nèi)部也維持著一個(gè)數(shù)據(jù)緩沖隊(duì)列(該隊(duì)列由一個(gè)鏈表構(gòu)成),當(dāng)生產(chǎn)者往隊(duì)列中放入一個(gè)數(shù)據(jù)時(shí),隊(duì)列會(huì)從生產(chǎn)者手中獲取數(shù)據(jù),并緩存在隊(duì)列內(nèi)部,而生產(chǎn)者立即返回;只有當(dāng)隊(duì)列緩沖區(qū)達(dá)到最大值緩存容量時(shí),才會(huì)阻塞生產(chǎn)者隊(duì)列,直到消費(fèi)者從隊(duì)列中消費(fèi)掉一份數(shù)據(jù),生產(chǎn)者線(xiàn)程會(huì)被喚醒,反之對(duì)于消費(fèi)者這端的處理也基于同樣的原理。
需要注意的是,如果構(gòu)造一個(gè)LinkedBlockingQueue對(duì)象,而沒(méi)有指定其容量大小,LinkedBlockingQueue會(huì)默認(rèn)一個(gè)類(lèi)似無(wú)限大小的容量(Integer.MAX_VALUE),這樣的話(huà),如果生產(chǎn)者的速度一旦大于消費(fèi)者的速度,也許還沒(méi)有等到隊(duì)列滿(mǎn)阻塞產(chǎn)生,系統(tǒng)內(nèi)存就有可能已被消耗殆盡了。
/** * Creates a {@code LinkedBlockingQueue} with a capacity of * {@link Integer#MAX_VALUE}. */ public LinkedBlockingQueue() { this(Integer.MAX_VALUE); } /** * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity. * * @param capacity the capacity of this queue * @throws IllegalArgumentException if {@code capacity} is not greater * than zero */ public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node<E>(null); }
使用 BlockingQueue 實(shí)現(xiàn)生產(chǎn)者消費(fèi)者問(wèn)題
public class ProducerConsumer { private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5); private static class Producer extends Thread { @Override public void run() { try { queue.put("product"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("produce.."); } } private static class Consumer extends Thread { String product = queue.take(); System.out.print("consume.."); } public static void main(String[] args) { for (int i = 0; i < 2; i++) { Producer producer = new Producer(); producer.start(); for (int i = 0; i < 5; i++) { Consumer consumer = new Consumer(); consumer.start(); for (int i = 0; i < 3; i++) { output: produce..produce..consume..consume..produce..consume..produce..consume..produce..consume..
到此,相信大家對(duì)“Java中常用阻塞隊(duì)列的問(wèn)題是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。