執行緒通信
1、場景:生產者和消費者問題
==倉庫、生產者、消費者
====倉庫只能存放一個產品,生產者將生產出來的產品放入倉庫,消費者將倉庫中產品取走
====如果倉庫中沒有產品,生產者將產品放入倉庫,否則停止生產并等待(阻塞),直到倉庫中的產品被消費者取走
====如果倉庫中有產品,消費者可以將產品取走消費,否則停止消費并等待,直到倉庫中再次放入產品為止
生產者和消費者共享一個資源,并且生產者和消費者之間相互依賴,互為條件,
==生產者消費者問題中,僅有synchronized是不夠的,
synchronized可以阻止并發更新同一個共享資源,實作了同步,但不能用來實作不同執行緒之間的訊息傳遞(通信)
2、執行緒通信的操作方法
(Object類的方法,只能在同步方法或同步代碼塊中使用,否則會拋出例外llegalMonitorStateException)
(1)wait() :執行緒一直等待,直到其它執行緒通知,會釋放鎖
(2)wait(long timeout):指定等待的毫秒數
(3)notify():喚醒一個處于等待狀態的執行緒
(4)notifyAll():喚醒同一個物件上所有呼叫wait()方法的執行緒,優先級高的執行緒先調度,
3、執行緒通信的方式:
(1)管程法(生產者 緩沖區 消費者)
并發協作模型:生產者消費者模式 管程法
==生產者:負責生產資料的模塊(方法、物件、執行緒、行程)
==消費者:負責處理資料的模塊(方法、物件、執行緒、行程)
==緩沖區:消費者不直接使用生產者的資料,生產者將生產好的資料放入緩沖區,消費者從緩沖區拿出資料
//測驗生產者消費者模式 : 管程法 (生產者 消費者 緩沖區)
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
new Productor(synContainer).start();
new Consumer(synContainer).start();
}
}
//生產者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Chicken chicken = new Chicken(i);
container.push(chicken);
System.out.println("productor product no."+i+"chicken");
}
}
}
//消費者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
?
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("no."+container.pop().num+"chicken ConSume");
}
}
}
//產品
class Chicken{
int num;
?
public Chicken(int num) {
this.num = num;
}
}
//緩沖區
class SynContainer{
//容器大小
Chicken[] chickens = new Chicken[10];
//數量
int count =0;
?
//生產者生產 放入
public synchronized void push(Chicken chicken){
//如果容器滿了
if (count==chickens.length){
//產品滿了通知消費者消費
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果沒滿 則生產 進入緩沖區
chickens[count]=chicken;
count++;
?
//生產者每生產產品就可以 通知消費者消費
this.notifyAll();
}
?
//消費者消費 取出
public synchronized Chicken pop(){