線程的等待與喚醒
-
(1)多個線程可以競争,也可以協作
賣票屬于競争
消費與生産屬于協作
吃貨每吃完一個包子,那麼就要告訴包子鋪生成包子
包子鋪每生産一個包子,就要通知吃貨去吃
-
(2)相關方法
void wait():讓目前線程等待,如果沒有人喚醒他,就一直等
void wait(long timeout):讓目前線程等待,如果到了指定的毫秒值還沒有人喚醒他就自己醒
void notify() 喚醒一個線程,喚醒的是目前對象鎖下的一個線程
void notifyAll() 喚醒所有線程,喚醒的是目前對象鎖下面的所有線程
這些方法一定要放在同步代碼塊中去使用,并且這些方法要通過鎖對象去調用
等待喚醒機制的代碼實作

//倉庫
class CangKu { //當作 鎖對象
//定義一個變量展現數量
public int productNum = 0;
}
//生産方
class ProductTask implements Runnable {
private CangKu cangKu; //共用一個倉庫不能自己建立,由外部傳入
public ProductTask(CangKu cangKu) {
this.cangKu = cangKu;
}
@Override
public void run() {
while (true) {
//通知與等待必須寫在同步代碼塊中
synchronized (this.cangKu)/*判斷是否有鎖可用*/ {/*有就進入*/
if (this.cangKu.productNum == 0) {
++ this.cangKu.productNum;
System.out.println("生産了一個産品 " + this.cangKu.productNum);
//通知消費者
this.cangKu.notify();
} else {
//有貨不用生産,等待通知
try {
System.out.println("生産方等待中.");
this.cangKu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//end if
}//end synchronized 出房間釋放鎖
}
}
}
//消費方
class ConsumerTask implements Runnable {
private CangKu cangKu;
public ConsumerTask(CangKu cangKu) {
this.cangKu = cangKu;
}
@Override
public void run() {
while (true) {
synchronized (this.cangKu) {
//判斷 是否為0
if (this.cangKu.productNum == 0) {
try {
System.out.println("消費方等待中.");
this.cangKu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//有貨可以吃
-- this.cangKu.productNum ;
System.out.println("消費了一個産品:" + this.cangKu.productNum);
//通知生産
this.cangKu.notify();
}//end if
}//end synchronized
}
}
}
public class Demo10 {
public static void main(String[] args) {
//任務對象
CangKu cangKu = new CangKu();
ProductTask productTask = new ProductTask(cangKu);
ConsumerTask consumerTask = new ConsumerTask(cangKu);
//定義線程
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(productTask);//生産
pool.submit(consumerTask);//消費
}
}
//1:邏輯要正确
//2: notify wait寫在同步代碼塊中,使用同一個對象 倉庫
//3: this.cangku.wait() this.wait() 前一個使用的是倉庫對象 ,後一個使用的是任務對象