wait()和notify()
wait()和notify()的方法并不是線程對象專屬的方法背传,Java中所有的對象都有這兩個方法裹赴。
object.wait(): 持有obj對象鎖的當前線程進入等待狀態(tài)启上,并釋放該對象的鎖。
object.notify(): 喚醒之前進入等待狀態(tài)的線程馅巷,使這些線程重新嘗試獲取對象鎖拦盹。
模擬生產者和消費者模式
倉庫,生產者舍哄,消費者三者之間宴凉,常常達到供需平衡的狀態(tài),即:
生產者生產指定量的產品表悬,便不能生產(wait)跪解,需要通知消費者進行消費(notify);
消費者消費完所有庫存,便不能再消費(wait)叉讥,需要告知生產者進行生產(notify)窘行。
如下代碼模擬以上模式:
import java.util.ArrayList;
import java.util.List;
public class ConsumerAndProducerTest {
public static void main(String[] args) {
// 模擬倉庫
List<Integer> list = new ArrayList<>();
// 創(chuàng)建生產者線程
Thread producer = new Thread(new Producer(list), "生產者");
// 創(chuàng)建消費者線程
Thread consumer = new Thread(new Consumer(list), "消費者");
// 同時啟動生產者和消費著
producer.start();
consumer.start();
}
}
/**
* 消費者類
*/
class Consumer implements Runnable {
final List<Integer> list;
int number = 0;
public Consumer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
while (true) {
// 判斷倉庫中商品是否空了
if (list.size() == 0) {
try {
list.wait(); // 沒有商品,進入等待狀態(tài)并釋放鎖
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消費庫存中第一件商品图仓,并返回商品編號
int id = list.remove(0);
System.out.println(Thread.currentThread().getName() + "消費了商品" + id + String.format("罐盔,已消費%d件商品!", ++number));
// 喚醒其他線程
list.notifyAll();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 生產者類
*/
class Producer implements Runnable {
final List<Integer> list;
int id = 0;
public Producer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
while (true) {
// 判斷倉庫中商品是否有指定數(shù)量庫存
if (list.size() >= 2) {
try {
list.wait(); // 有商品救崔,進入等待狀態(tài)并釋放鎖
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生產
list.add(++id);
System.out.println(Thread.currentThread().getName() + "生產了商品" + id + String.format(", 現(xiàn)倉庫有%d件未售出惶看!", list.size()));
// 喚醒其他線程
list.notifyAll();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}