多執行緒學習之生產者與消費者
阿新 • • 發佈:2018-12-11
感悟: 生產者和消費者其實就是一個很簡單的一個多執行緒同步的例子,但是我卻花了好多天才能理解。反思下來就是缺乏實踐,這聽起來感覺很簡單的一個道理,但是能做到可就很難了。當初在看這個生產者和消費者例項的時候,看著感覺程式碼能簡單,大致上能理解,但是到了轉天自己卻又寫不出來了,才知道是自己還沒有理解透徹。現在動了一次手實踐一番以後,不說理解透徹,理解個90%還是沒問題的。
基礎準備: notify()是Object類的一個方法,其作用在java-api中說到,喚醒在此物件監視器上等待的單個執行緒,之前一直理解為哪個執行緒呼叫的該方法就喚醒哪個執行緒,這就大錯特錯了。
程式碼實現:
這裡模擬的是生產者生產蘋果,放在公共的盒子上,消費者從公共的盤子上獲取水果。
先寫個公共盤子類PublicBox:
package ThreadProducerAndConsumer; /** * 公共的盒子 * Created by Curtain on 2018/9/24. */ public class PublicBox { private int apple = 0; //增加蘋果的方法 public synchronized void increace(){ while (apple == 5){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } apple++; System.out.println("生成蘋果成功!"); notify(); } public synchronized void decreace(){ while (apple == 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } apple--; System.out.println("消費蘋果成功!"); notify(); } }
寫個生產者類Producer:
package ThreadProducerAndConsumer; /** * 生產者(定義10次) * Created by Curtain on 2018/9/24. */ public class Producer implements Runnable{ private PublicBox box; public Producer(PublicBox box){ this.box = box; } @Override public void run() { //生產10次蘋果 for (int i = 0; i < 10; i++){ try { System.out.println("pro i:" + i); Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } box.increace(); } } }
寫個消費者類Consumer:
package ThreadProducerAndConsumer;
/**
* 消費者
* Created by Curtain on 2018/9/24.
*/
public class Consumer implements Runnable{
private PublicBox box;
public Consumer(PublicBox box){
this.box = box;
}
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println("con i:" + i);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
box.decreace();
}
}
}
最後就是測試類:
package ThreadProducerAndConsumer;
/**
* 生產和和消費者測試
* Created by Curtain on 2018/9/24.
*/
public class Test01 {
public static void main(String[] args) {
PublicBox box = new PublicBox();
Consumer con = new Consumer(box);
Producer pro = new Producer(box);
Thread t1 = new Thread(con);
Thread t2 = new Thread(pro);
t1.start();
t2.start();
}
}
執行結果: