wait/notify應用舉例實現生產者和消費者通訊模型
阿新 • • 發佈:2021-02-13
下面,在不考慮實用性等前提下,我們會實現一個最簡單的生產者、消費者模型,僅僅只用來理解wait/notify的機制。
在這個例子裡,將啟動一個生產者執行緒、一個消費者執行緒。生產者檢測到有產品可供消費時,通知消費者(notify)進行消費,同時自己進入等待狀態(wait),如果檢測到沒有產品可供消費,則進行生產。
消費者檢測到有產品可供消費時,則進行消費,消費結束沒通知生產者進行生產,如果檢測到沒有產品可供消費,自然也通知生產者進行生產。
也就是說,生產者執行緒和消費者執行緒會互相等待和互相通知。他們會爭奪同一個物件obj的鎖,實現執行緒之間的通訊
Product類:
public class Product {
private static Integer count = 0;
public static void add() {
count++;
}
public static void delete() {
count--;
}
public static Integer getCount(){
return count;
}
}
Produce類:
public class Produce implements Runnable {
private Object object;
public Produce(Object object) {
this.object = object;
}
@Override
public void run() {
synchronized (object) {
System.out.println("++++ 進入生產者執行緒");
System.out.println("++++ 產品數量:" + Product.getCount());
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (Product.getCount() <= 0) {
System.out.println("++++ 開始生產!");
Product.add();
System.out.println("++++ 生產後產品數量:" + Product.getCount());
}else {
try {
// 通知消費者進行消費,自己進入等待
object.notify();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
Consume類:
import java.util.concurrent.TimeUnit;
public class Consume implements Runnable {
private Object object;
public Consume(Object object) {
this.object = object;
}
@Override
public void run() {
synchronized (object) {
System.out.println("---- 進入消費者執行緒");
System.out.println("---- 當前產品數量:" + Product.getCount());
// 判斷條件是否滿足(有沒有產品可以消費),若不滿足則等待
while (true) {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (Product.getCount() <= 0) {
try {
System.out.println("---- 沒有產品,進入等待");
// 通知生產者生產,自己進入等待
object.notify();
object.wait();
System.out.println("---- 結束等待,開始消費");
Product.delete();
System.out.println("---- 消費後產品數量:" + Product.getCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("---- 已有產品,直接消費");
Product.delete();
System.out.println("---- 消費後產品數量:" + Product.getCount());
}
}
}
}
}
測試主類
public class ThreadTest {
static final Object obj = new Object();
public static void main(String[] args) throws Exception {
Thread consume = new Thread(new Consume(obj), "Consume");
Thread produce = new Thread(new Produce(obj), "Produce");
// 先啟動消費者
consume.start();
produce.start();
}
}
程式會一直執行下去。