java多執行緒之消費生產模型-使用synchronized解決虛假喚醒

wsilj發表於2020-12-11
package com.wenshao.juc;

/**
 * 生產者和消費者案例
 * 
 * @author Administrator
 *
 */
public class TestProductorAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();

		Productor productor = new Productor(clerk);
		Consumer consumer = new Consumer(clerk);

		new Thread(productor, "生產者 A").start();
		new Thread(consumer, "消費者 B").start();
		new Thread(productor, "生產者 C").start();
		new Thread(consumer, "消費者 D").start();
	}
}

class Clerk {

	private int product = 0;

	// 1. 進貨
	public synchronized void get() {
		while(product >= 1) { // 為了避免虛假喚醒問題,wait() 應該總是使用在迴圈中
			System.out.println("產品已滿");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + ":" + ++product);
		this.notifyAll();

	}

	// 2. 賣貨
	public synchronized void sale() {
		while (product <= 0) {
			System.out.println("缺貨!");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + ":" + --product);
		this.notifyAll();
	}

}

// 生產者
class Productor implements Runnable {

	private Clerk clerk;

	public Productor(Clerk clerk) {
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
		for (int i = 0; i <= 20; i++) {
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.get();
		}
	}
}

// 消費者
class Consumer implements Runnable {

	private Clerk clerk;

	public Consumer(Clerk clerk) {
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
		for (int i = 0; i <= 20; i++) {
			clerk.sale();
		}
	}
}

相關文章