java多线程之消费生产模型-使用synchronized解决虚假唤醒

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();
		}
	}
}

posted @ 2020-12-11 19:40  wsilj  阅读(136)  评论(0编辑  收藏  举报