生活随笔
收集整理的這篇文章主要介紹了
JAVA线程间协作:Condition
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-multi-thread-of-condition/
? ? 內(nèi)置條件隊列存在一些缺陷。每個內(nèi)置鎖都只能有一個相關(guān)聯(lián)的條件隊列,因而在像BounderBuffer這種類中,多個線程可能在同一個條件隊列上等待不同的條件謂詞,并且在最常見的加鎖模式下公開條件隊列對象。這些因素都使得無法滿足在使用notifyAll時所有等待線程為統(tǒng)一類型的需求。如果想編寫一個帶有多個條件謂詞的并發(fā)對象,或者想獲得除了條件隊列可見性之外的更多控制權(quán),就可以使用顯示的Lock和Condition而不是內(nèi)置鎖和條件隊列,這是一種更靈活的選擇。
? ? 一個Condition和一個Lock關(guān)聯(lián)在一起,就想一個條件隊列和一個內(nèi)置鎖相關(guān)聯(lián)一樣。要創(chuàng)建一個Condition,可以在相關(guān)聯(lián)的Lock上調(diào)用Lock.newCondition方法。正如Lock比內(nèi)置加鎖提供了更為豐富的功能,Condition同樣比內(nèi)置條件隊列提供了更豐富的功能:在每個鎖上可存在多個等待、條件等待可以是可中斷的或者不可中斷的、基于時限的等待,以及公平的或非公平的隊列操作。
? ? 與內(nèi)置條件隊列不同的是,對于每個Lock,可以有任意數(shù)量的Condition對象。Condition對象繼承了相關(guān)的Lock對象的公平性,對于公平的鎖,線程會依照FIFO順序從Condition.await中釋放。
Condition接口:
?
public interface Condition{void await() throws InterruptedException;boolean await(long time, TimeUnit unit) throws InterruptedException;long awaitNanos(long nanosTimeout) throws InterruptedException;void awaitUniterruptibly();boolean awaitUntil(Date deadline) throws InterruptedException;void signal();void signalAll();
}
? ? 注意:在Condition對象中,與wait,notify和notifyAll方法對于的分別是await,signal,signalAll。但是,Condition對Object進(jìn)行了擴(kuò)展,因而它也包含wait和notify方法。一定要確保使用的版本——await和signal.
官方使用方法如下:
class BoundedBuffer
{final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException{lock.lock();try{while (count == items.length)notFull.await();items[putptr] = x;if (++putptr == items.length)putptr = 0;++count;notEmpty.signal();}finally{lock.unlock();}}public Object take() throws InterruptedException{lock.lock();try{while (count == 0)notEmpty.await();Object x = items[takeptr];if (++takeptr == items.length)takeptr = 0;--count;notFull.signal();return x;}finally{lock.unlock();}}
}
? ? 或者通過一個實(shí)際的例子來解釋Condition的用法:
? ? 我們要打印1-9這0個數(shù)字,由A線程先打印1-3,然后由B線程打印4-6,然后再由A線程打印7-9.我們采用Condition來演示解決方法:
package com.cooperation;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TestCondition
{private static int value = 1;private Lock lock = new ReentrantLock();private Condition Condition456 = lock.newCondition();private Condition Condition789 = lock.newCondition();class ThreadA implements Runnable{@Overridepublic void run(){try{lock.lock();System.out.println("首先輸出1-3");while(value<=3){System.out.println(value++);}Condition456.signal();}finally{lock.unlock();}try{lock.lock();while(value<=6){Condition789.await();}System.out.println("輸出7-9");while(value<=9){System.out.println(value++);}}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}}}class ThreadB implements Runnable{@Overridepublic void run(){try{lock.lock();while(value<=3){Condition456.await();}}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}try{lock.lock();System.out.println("輸出4-6");while(value<=6){System.out.println(value++);}Condition789.signal();}finally{lock.unlock();}}}public static void main(String[] args){TestCondition test = new TestCondition();Thread threadA = new Thread(test.new ThreadA());Thread threadB = new Thread(test.new ThreadB());threadA.start();threadB.start();}}
輸出結(jié)果:
?
?
首先輸出1-3
1
2
3
輸出4-6
4
5
6
輸出7-9
7
8
9
? ? 如果需要采用Object方法的wait,notify,notifyAll方法實(shí)現(xiàn)這個實(shí)例可以參考:http://outofmemory.cn/java/java.util.concurrent/thread-sync-with-object-wait-notify-notifyAll
? ? 同樣可以擴(kuò)張,ThreadA打印123,ThreadB打印456,再讓ThreadA打印789,最后然ThreadB打印10 11 12.如下:
package com.cooperation;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TestCondition
{private static int value = 1;private Lock lock = new ReentrantLock();private Condition Condition456 = lock.newCondition();private Condition Condition789 = lock.newCondition();private Condition Condition101112 = lock.newCondition();class ThreadA implements Runnable{@Overridepublic void run(){try{lock.lock();System.out.println("首先輸出1-3");while(value<=3){System.out.println(value++);}Condition456.signal();}finally{lock.unlock();}try{lock.lock();while(value<=6){Condition789.await();}System.out.println("輸出7-9");while(value<=9){System.out.println(value++);}Condition101112.signal();}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}}}class ThreadB implements Runnable{@Overridepublic void run(){try{lock.lock();while(value<=3){Condition456.await();}}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}try{lock.lock();System.out.println("輸出4-6");while(value<=6){System.out.println(value++);}Condition789.signal();}finally{lock.unlock();}try{lock.lock();while(value<=9){Condition101112.await();}}catch (InterruptedException e){e.printStackTrace();}finally{lock.unlock();}try{lock.lock();System.out.println("輸出10-12");while(value<=12){System.out.println(value++);}}finally{lock.unlock();}}}public static void main(String[] args){TestCondition test = new TestCondition();Thread threadA = new Thread(test.new ThreadA());Thread threadB = new Thread(test.new ThreadB());threadA.start();threadB.start();}
}
輸出結(jié)果:
?
?
首先輸出1-3
1
2
3
輸出4-6
4
5
6
輸出7-9
7
8
9
輸出10-12
10
11
12
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-multi-thread-of-condition/
?
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生
總結(jié)
以上是生活随笔為你收集整理的JAVA线程间协作:Condition的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。