JAVA並發編程6_線程協作/生產者-消費者

來源:互聯網
上載者:User

標籤:線程   java   

前面通過同步鎖來同步任務的行為,兩個任務在交替訪問共用資源的時候,可以通過使用同步鎖使得任何時候只有一個任務可以訪問該資源,見部落格:線程同步之synchronized關鍵字。下面主要講的是如何使任務彼此間可以協作,使得多個任務可以一起工作去解決木某個問題,因為有些問題中,某些部分必須在其他部分被解決之前解決,就像在餐廳服務員要端菜就必須有廚師做好了菜。在任務協作時,可以讓任務自身掛起,直至某些外部條件發生變化,表示是時候讓這個任務向前推動了為止。

wait/notify

wait方法會在等待外部世界產生變化的時候將任務掛起,並且只有在notify或notifyAll發生時即表示發生了某些感興趣的事物,這個任務才會被喚醒並去檢查所產生的變化。

wait方法表示主動釋放同步鎖並將任務掛起,當前任務處於waiting狀態。由於會釋放鎖,意味著該對象的其他synchronized方法可以在wait期間被調用。而恰好在這些方法裡面發生了喚醒被掛起任務所感興趣的變化。

當調用wait方法時,就是再聲明:“我已經剛剛做完能做的所有事情,因此我要在這裡等待,但是我希望其他的synchronized操作在條件適合的情況下通知我讓我繼續執行。”

notify方法用來喚醒處於wait狀態的任務,當notify/notifyAll因某個特定的鎖而被調用時,只有等待這個鎖的任務才會被喚醒。

註:

wait/notify/notifyAll這些方法是基類Object的一部分。因為任何Object都可以作為同步鎖。並且只能在同步控制方法或者同步代碼塊裡面才能調用這些方法,如果在非同步方法裡面調用,程式能通過編譯,啟動並執行時候會報錯IllegalMonitorStateException。也就是說調用這些方法必須擁有對象鎖(同步鎖)。


生產者消費者

在一個飯店裡,有一個廚師和一個服務員,這個服務員必須等待廚師準備好膳食,當廚師準備好時,他會通知服務員,之後服務員上菜,然後返回繼續等待。這是一個任務協作的執行個體。廚師代表生產者,而服務員代表消費者。

class Restaurant{private Object obj;public void put(){while (true) {synchronized (this) {while (obj != null) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}obj = new Object();System.out.print("Order up!  ");        notifyAll();}}}public void get(){while (true) {synchronized (this) {while (obj == null) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("waiter get meal");obj = null;notifyAll();}}}}class Chef extends Thread{private Restaurant restaurant;public Chef(Restaurant restaurant){this.restaurant = restaurant;}@Overridepublic void run() {restaurant.put();}}class Waiter extends Thread{private Restaurant restaurant;public Waiter(Restaurant restaurant){this.restaurant = restaurant;}@Overridepublic void run() {restaurant.get();}}public class Test {public static void main(String[] args) {Restaurant restaurant = new Restaurant();Chef produce = new Chef(restaurant);Waiter consumer = new Waiter(restaurant);produce.start();consumer.start();}}
輸出:

Order up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get mealOrder up!  waiter get meal...

Chef和Waiter通過Resaurant打交道,在兩個線程中,一個線程也就是廚師線程掛起等待服務員線程消費做好的meal,他所感興趣的事物就是obj是否為null。一旦obj為null也就是服務員將這份meal消費了,就會喚醒服務員消費這份meal。

另一個線程也就是服務員線程掛起等待廚師做好meal,他所感興趣的事物也是obj是否為null。一旦obj不為null,他會消費這份meal,並且喚醒廚師做下一份meal。


一般,wait會被封裝在while()語句中,這個語句在不斷地測試正在等待的事物。可否換成if?初步看上去,一旦被喚醒,這個obj必然時刻獲得的,因為任務被喚醒就是發生了其感興趣的事物,可是,正事由於問題發生在並發應用中。其他任務有可能會在當前任務被喚醒時,突然插足拿走obj。因為常用下面wait的慣用法

while(conditiopnIsNotMet)

wait();

這樣才能更加安全,保證了在退出迴圈之前條件得到滿足。






JAVA並發編程6_線程協作/生產者-消費者

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.