方法/ 作用
wait: 線程自動釋放佔有的對象鎖,並等待notify。
notify: 隨機喚醒一個正在wait當前對象的線程,並讓被喚醒的線程拿到對象鎖
notifyAll: 喚醒所有正在wait當前對象的線程,但是被喚醒的線程會再次去競爭對象鎖。因爲一次只有一個線程能拿到鎖,所有其他沒有拿到鎖的線程會被阻塞。推薦使用。
Java中規定,在調用這三個方法時,當前線程必須獲得對象鎖。因此就得配合synchronized關鍵字來使用。在synchronized拿到對象鎖之後,synchronized代碼塊或者方法中,必定是會持有對象鎖的,因此就可以使用wait()或者notify()。
使用wait()、notify()來實現一個生產者、消費者模式:
class ProductAndCusumer {
private static final Integer MAX_CAPACITY = 5;
private static LinkedList<String> queue = new LinkedList<>(); //需要將queue作爲多線程操作的鎖
static class Producter extends Thread {
@Override
public void run() {
while (true) {
synchronized (queue) {
if (queue.size() >= MAX_CAPACITY * 2) {
System.out.println("緩衝隊列已滿");
//停止生產產品,此時在生產者的線程中,調用queue.wait主動去釋放鎖,
//讓當前消費線程進入等待喚醒去拿鎖
try {
queue.wait();
} catch (Exception e) {
}
}
//沒有滿,繼續生產
String product = "生產:" + Thread.currentThread().getName();
System.out.println(product);
queue.add(product);
try {
Thread.sleep(500);
} catch (Exception e) {
}
try {
queue.notifyAll(); //喚醒所有線程拿鎖
} catch (Exception e) {
}
}
}
}
}
static class Consumer extends Thread {
@Override
public void run() {
while (true) {
synchronized (queue) {
if (queue.isEmpty()) {
System.out.println("緩衝隊列爲空,暫無消費產品");
try {
queue.wait();
} catch (Exception e) {
}
}
try {
System.out.println("消費:" + queue.pop());
Thread.sleep(500);
queue.notifyAll();
} catch (Exception e) {
}
}
}
}
}
public static void main(String[] args) {
new Producter().start();
new Consumer().start();
}
}