synchronized版,使用wait、notify
public class demo01 catch (interruptedexception e)
}},"生產者").start();
//消費者a去購買商品
new thread(()-> catch (interruptedexception e)
}},"消費者a").start();
//消費者b去購買商品
new thread(()-> catch (interruptedexception e)
}},"消費者b").start()
}}class shop
goodsnum -= num;
system.out.println(thread.currentthread().getname()+"買走了"+num+"件商品,還剩餘"+goodsnum+"件商品");
this.notifyall();
}public synchronized void buygoods(int num) throws interruptedexception
goodsnum += num;
system.out.println(thread.currentthread().getname()+"送來了"+num+"件商品,還剩餘"+goodsnum+"件商品");
this.notifyall();
}}
有可能出現的問題:虛假喚醒
表現:
虛假喚醒的表現為: 有時候資源會出現"超賣"現象. 也就是出現負數, 而這是不應該出現的. 關鍵點就是判斷合法性的時候, 使用了if進行判斷.
過程:
- 在消費者進入到購買方法中時,會告知商品為0,發生阻塞(wait)會將鎖釋放,這是其他消費執行緒也進入,發生阻塞,等到生產者將商品補充之後,再去進行商品的購買(num--),這時if只會判斷一次,所以就可能發生num=-1;
解決辦法:
將if換成while
使用lock鎖和 condition
獲取condition的方法:
lock lock = new reentrantlock();
condition condition1 = lock.newcondition();
condition主要方法:
public class test01
},"執行緒a").start();
new thread(()->
},"執行緒b").start();
new thread(()->
},"執行緒c").start();
new thread(()->
},"執行緒d").start();
}}class a
num++;
system.out.println(thread.currentthread().getname()+"->"+num);
condition.signalall();//喚醒
} catch (exception e) finally
}public synchronized void decrement()
num--;
system.out.println(thread.currentthread().getname()+"->"+num);
condition.signalall();
} catch (exception e) finally
}}
使用condition精準通知和喚醒執行緒:
//有三個方法:
public void printa(){}//執行緒a執行
public void printb(){}//執行緒b執行
public void printc(){}//執行緒c執行
private condition condition1 = lock.newcondition();//監聽執行緒a
private condition condition2 = lock.newcondition();//監聽執行緒b
private condition condition3 = lock.newcondition();//監聽執行緒c
//在printa方法執行完之後,用condition2去喚醒執行緒b執行priintb
//在printb方法執行完之後,用condition3去喚醒執行緒b執行priintc
//在printa方法執行完之後,用condition1去喚醒執行緒b執行priinta
//可以達到condition精準的通知和喚醒執行緒
具體操作**:
/**
* a執行完呼叫b,b執行完呼叫c c執行完呼叫a
*/public class test02
},"a").start();
//執行緒b
new thread(()->
},"b").start();
//執行緒c
new thread(()->
},"c").start();
}}class data1
num=2;
//通知condition2去喚醒執行緒b
condition2.signal();
system.out.println(thread.currentthread().getname()+":->aaaa");
} catch (exception e) finally
}public void printb()
num = 3;
//通知condition3去喚醒執行緒c
condition3.signal();
system.out.println(thread.currentthread().getname()+":->bbbb");
} catch (exception e) finally
}public void printc()
num = 1;
//通知condition1去喚醒執行緒a
condition1.signal();
system.out.println(thread.currentthread().getname()+":->cccc");
} catch (exception e) finally
}}
生產者消費者 生產者與消費者模式
一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...
生產者消費者問題的兩種寫法
問題 乙個固定容量的同步容器,有get方法和put方法,和size 方法。n個生產者不斷往裡面put,m個消費者不斷從中get。方式一 object的wait和notify public class testpandc p i t.start try catch interruptedexcepti...
生產者與消費者
include include include include include include define size of buffer 10 int buffer size of buffer 緩衝陣列 int in 0,out 0 採用迴圈佇列方式進行陣列的訪問 宣告訊號量 sem t ful...