日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LinkedBlockingQueue的put,take方法

發布時間:2024/2/28 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LinkedBlockingQueue的put,take方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

put操作:在LinkedBlockingQueue?中有putlcok和takelock倆把鎖,put操作使用putlock這把鎖,利用lockInterruptibly方法加鎖,該方法的作用為:如果該線程被標記為中斷,可拋出異常。加鎖之后,判斷count是否等于容量,相等的話條用await()方法線線程加到條件隊列中去,直到喚醒,把元素加入到隊列,然后判斷一下count+1如果還沒有達到容量值的話,再次調用notfull的signal方法,因為有可能多個線程阻塞到notfull條件隊列中。最后釋放鎖。

釋放完鎖之后,如果原來count值為0的話,現在加了一個元素,調用signalNotEmpty方法,執行notEmpty.signal(),值得注意的是此過程得用takelock加鎖,原因是防止其他線程消費了。

public void put(E e) throws InterruptedException {// 不允許null元素if (e == null) throw new NullPointerException();int c = -1;// 新建一個節點Node<E> node = new Node<E>(e);final ReentrantLock putLock = this.putLock;final AtomicInteger count = this.count;// 使用put鎖加鎖putLock.lockInterruptibly();try {// 如果隊列滿了,就阻塞在notFull條件上// 等待被其它線程喚醒while (count.get() == capacity) {notFull.await();}// 隊列不滿了,就入隊enqueue(node);// 隊列長度加1c = count.getAndIncrement();// 如果現隊列長度如果小于容量// 就再喚醒一個阻塞在notFull條件上的線程// 這里為啥要喚醒一下呢?// 因為可能有很多線程阻塞在notFull這個條件上的// 而取元素時只有取之前隊列是滿的才會喚醒notFull// 為什么隊列滿的才喚醒notFull呢?// 因為喚醒是需要加putLock的,這是為了減少鎖的次數// 所以,這里索性在放完元素就檢測一下,未滿就喚醒其它notFull上的線程// 說白了,這也是鎖分離帶來的代價if (c + 1 < capacity)notFull.signal();} finally {// 釋放鎖putLock.unlock();}// 如果原隊列長度為0,現在加了一個元素后立即喚醒notEmpty條件if (c == 0)signalNotEmpty(); }private void enqueue(Node<E> node) {// 直接加到last后面last = last.next = node; } private void signalNotEmpty() {final ReentrantLock takeLock = this.takeLock;// 加take鎖takeLock.lock();try {// 喚醒notEmpty條件notEmpty.signal();} finally {// 解鎖takeLock.unlock();} }

?take操作:其實和put的操作相反就行,利用takelock加鎖,如果count值為0,那么notEmpty.await()加入到notEmpty的條件隊列中去直至喚醒,喚醒之后取隊頭元素,如果此時count-1還大于0,那么調用signal()喚醒阻塞再notEmpty條件隊列的線程。然后釋放鎖。最后調用signalNotFull,喚醒阻塞在notfull條件隊列上的線程,此過程利用putlock鎖來防止其他線程執行put操作進而可能導致隊列又滿了

public E take() throws InterruptedException {E x;int c = -1;final AtomicInteger count = this.count;final ReentrantLock takeLock = this.takeLock;// 使用takeLock加鎖takeLock.lockInterruptibly();try {// 如果隊列無元素,則阻塞在notEmpty條件上while (count.get() == 0) {notEmpty.await();}// 否則,出隊x = dequeue();// 獲取出隊前隊列的長度c = count.getAndDecrement();// 如果取之前隊列長度大于1,則喚醒notEmptyif (c > 1)notEmpty.signal();} finally {// 釋放鎖takeLock.unlock();}// 如果取之前隊列長度等于容量// 則喚醒notFullif (c == capacity)signalNotFull();return x; }private E dequeue() {// head節點本身是不存儲任何元素的// 這里把head刪除,并把head下一個節點作為新的值// 并把其值置空,返回原來的值Node<E> h = head;Node<E> first = h.next;h.next = h; // help GChead = first;E x = first.item;first.item = null;return x; }private void signalNotFull() {final ReentrantLock putLock = this.putLock;putLock.lock();try {// 喚醒notFullnotFull.signal();} finally {putLock.unlock();} }

總結

以上是生活随笔為你收集整理的LinkedBlockingQueue的put,take方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。