Java并發(fā)編程:線程間的協(xié)作wait()掀宋、notify()、notifyAll()和Condition

java并發(fā)編程協(xié)作有兩種方式:

  • 利用Object對(duì)象下面的wait()仲锄、notify()或者notifyAll()
  • 利用Condition的await()劲妙、singnal()或者singnalAll()
    其中需要注意的是:
    對(duì)于方式1、調(diào)用wait()儒喊、notify()或者notifyAll() 必須在同步塊或者同步方法中進(jìn)行(synchronized塊或者synchronized方法)镣奋。
    對(duì)于方式2、await()怀愧、singnal()或者singnalAll()必須在lock()和unlock()方法中進(jìn)行侨颈。
    下面以常見的生成著和消費(fèi)者模型為例余赢,說明這兩種方式的使用。我們以購(gòu)物車為例哈垢,當(dāng)購(gòu)物車為空的時(shí)候妻柒,不允許從購(gòu)物車中拿操作,當(dāng)購(gòu)物車滿5個(gè)商品的時(shí)候?yàn)闈M温赔,不允許再放入商品蛤奢。本例僅僅為說明以上兩個(gè)方式的使用,不具有說明實(shí)際意義

使用方式1

ShoppingCar.java

public class ShoppingCar {
    private Queue<String> queue = null;
    Lock lock = new ReentrantLock();
    public ShoppingCar(Queue<String> queue) {
        super();
        this.queue = queue;
    }

    public  void getGood(String i){
        
        synchronized (queue) {
            System.out.println("current queue size is "+queue.size()+" car"+i+" start get good");
            while(queue.isEmpty()){ 
                try {
                    System.out.println("car "+i+" get good stop");//當(dāng)queue空的時(shí)候陶贼,等待啤贩,并讓出對(duì)象鎖
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String g = queue.poll();
            System.out.println("car "+i+" get good "+ g +" suceed");
            queue.notifyAll();
        }
    }
    public  void addGood(String i,String g){
    
        synchronized (queue) {
            System.out.println("current queue size is "+queue.size()+" car"+i+" start add "+g);
            while(queue.size()>=5){
                try {
                    System.out.println("car"+i+" add"+g+" stop");//當(dāng)queue滿的時(shí)候,等待拜秧,并讓出對(duì)象鎖
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("car "+i+" add "+g+" suceed");
            queue.add(g);
            queue.notifyAll();
        }
    }
}

使用方式2

ShoppingCar2.java

public class ShoppingCar2 {
    private Queue<String> queue = null;
    Lock lock = new ReentrantLock();
    Condition empty =  lock.newCondition();
    Condition full = lock.newCondition();
    public ShoppingCar2(Queue<String> queue) {
        super();
        this.queue = queue;
    }

    public  void getGood(String i){
        lock.lock();
        try{
            System.out.println("current queue size is "+queue.size()+" car"+i+" start get good");
            while(queue.isEmpty()){
                try {
                    System.out.println("car "+i+" get good stop");//當(dāng)queue空的時(shí)候痹屹,等待,并讓出對(duì)象鎖
                    empty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            String g = queue.poll();
            System.out.println("car "+i+" get good "+ g +" sssuceed");
            full.signalAll();
        }finally{
            lock.unlock();
        }
        
    }
    public  void addGood(String i,String g){
    
        lock.lock();
        try{
            System.out.println("current queue size is "+queue.size()+" car"+i+" start add "+g);
            while(queue.size()>=5){
                try {
                    System.out.println("car"+i+" add "+g+" stop");//當(dāng)queue滿的時(shí)候枉氮,等待志衍,并讓出對(duì)象鎖
                    full.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("car "+i+" add "+g+" suceed");
            queue.add(g);
            empty.signalAll();
        }finally{
        lock.unlock();
        }
    }
}

調(diào)用:

public class Demo {
    public static void main(String[] args) {
        ShoppingCar2 car = new ShoppingCar2(new LinkedList<String>());
                ExecutorService addser = Executors.newCachedThreadPool();
                ExecutorService getser = Executors.newCachedThreadPool();
                for(int i=0;i<10;i++)
                      addser.submit(new AddThread(i, car));
                for(int i=0;i<10;i++)
                       getser.submit(new GetThread(i, car));
                addser.shutdown();
                getser.shutdown();      
    }   
    public  static class AddThread implements Runnable{
        ShoppingCar2 car = null;
        int id;
        public AddThread(int i,ShoppingCar2 car){
            this.car = car;
            this.id = i;
        }
        @Override
        public void run() {
            while(true){
            car.addGood(String.valueOf(id),String.valueOf((int)(100*Math.random())));
            try {
                Thread.currentThread().sleep((int)(1000*Math.random())*10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
        }
    }
    public  static class GetThread implements Runnable{
        ShoppingCar2 car = null;
        int id;
        public GetThread(int i,ShoppingCar2 car){
            this.car = car;
            this.id = i;
        }
        @Override
        public void run() {
            while(true){
            car.getGood(String.valueOf(id));
            try {
                Thread.currentThread().sleep((int)(1000*Math.random())*10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
        }
    }
}

說明:購(gòu)物車有兩個(gè)操作,一個(gè)get商品聊替、一個(gè)add商品楼肪、在Demo類中我們有一個(gè)AddThread類專門去add商品、一個(gè)GetThread類專門去get商品惹悄。main方法中春叫,我們分別產(chǎn)出10個(gè)Get線程和10個(gè)Add線程去執(zhí)行商品的add和get操作。
商品用一個(gè)隨機(jī)生成的數(shù)字代替泣港,get和add商品的時(shí)間也隨機(jī)指定暂殖。執(zhí)行結(jié)果如下:
current queue size is 0 car0 start add 53
car 0 add 53 suceed
current queue size is 1 car3 start add 58
car 3 add 58 suceed
current queue size is 2 car4 start add 82
car 4 add 82 suceed
current queue size is 3 car2 start add 33
car 2 add 33 suceed
current queue size is 4 car6 start add 99
car 6 add 99 suceed
current queue size is 5 car7 start add 53
car7 add 53 stop</span>
current queue size is 5 car1 start add 45
car1 add 45 stop
current queue size is 5 car8 start add 59
car8 add 59 stop
current queue size is 5 car5 start add 58
car5 add 58 stop
current queue size is 5 car9 start add 88
car9 add 88 stop
current queue size is 5 car0 start get good
car 0 get good 53 sssuceed
current queue size is 4 car3 start get good
car 3 get good 58 sssuceed
current queue size is 3 car1 start get good
car 1 get good 82 sssuceed
current queue size is 2 car2 start get good
car 2 get good 33 sssuceed
current queue size is 1 car4 start get good
car 4 get good 99 sssuceed
car 7 add 53 suceed</span>
car 1 add 45 suceed
car 8 add 59 suceed
car 5 add 58 suceed
car 9 add 88 suceed
current queue size is 5 car5 start get good
car 5 get good 53 sssuceed
current queue size is 4 car6 start get good
car 6 get good 45 sssuceed
current queue size is 3 car8 start get good
car 8 get good 59 sssuceed
current queue size is 2 car9 start get good
car 9 get good 58 sssuceed
current queue size is 1 car7 start get good
car 7 get good 88 sssuceed
current queue size is 0 car4 start add 88
car 4 add 88 suceed
current queue size is 1 car9 start get good
car 9 get good 88 sssuceed
current queue size is 0 car5 start add 1
car 5 add 1 suceed
current queue size is 1 car9 start get good
car 9 get good 1 sssuceed
current queue size is 0 car9 start get good
car 9 get good stop
current queue size is 0 car1 start add 70
car 1 add 70 suceed

我們選取部分的結(jié)果分析,看標(biāo)注的兩個(gè)地方
car7 add 53 stop
執(zhí)行到這里時(shí)当纱,購(gòu)物車滿了呛每,沒有添加到購(gòu)物車
car 7 add 53 suceed
到這里時(shí)候,由于有線程在get商品坡氯,此時(shí)購(gòu)物車中商品小于5個(gè)了晨横,可以添加商品了,就添加成功

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末箫柳,一起剝皮案震驚了整個(gè)濱河市颓遏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滞时,老刑警劉巖叁幢,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坪稽,居然都是意外死亡曼玩,警方通過查閱死者的電腦和手機(jī)鳞骤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來黍判,“玉大人豫尽,你說我怎么就攤上這事∏晏” “怎么了美旧?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)贬墩。 經(jīng)常有香客問我榴嗅,道長(zhǎng),這世上最難降的妖魔是什么陶舞? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任嗽测,我火速辦了婚禮,結(jié)果婚禮上肿孵,老公的妹妹穿的比我還像新娘唠粥。我一直安慰自己,他們只是感情好停做,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布晤愧。 她就那樣靜靜地躺著,像睡著了一般蛉腌。 火紅的嫁衣襯著肌膚如雪官份。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天眉抬,我揣著相機(jī)與錄音贯吓,去河邊找鬼懈凹。 笑死蜀变,一個(gè)胖子當(dāng)著我的面吹牛介评,可吹牛的內(nèi)容都是我干的库北。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼们陆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了坪仇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤椅文,失蹤者是張志新(化名)和其女友劉穎惜颇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體少辣,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年漓帅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忙干。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡器予,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出豪直,到底是詐尸還是另有隱情劣摇,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布弓乙,位于F島的核電站末融,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏暇韧。R本人自食惡果不足惜勾习,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懈玻。 院中可真熱鬧巧婶,春花似錦、人聲如沸涂乌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽湾盒。三九已至湿右,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罚勾,已是汗流浹背毅人。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尖殃,地道東北人丈莺。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像送丰,于是被迫代替她去往敵國(guó)和親缔俄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容