生产者-消费者的经典例子

 

package fighting;

public class ThreadProducerConsumer {

	/**
	 * 生产者-消费者的例子
	 * 对于多个生产者和消费者,为什么要定义while判断标记,
	 * 原因:让被唤醒的线程再一次判断标记。
	 * 
	 * 总结:当出现多个生产者和消费者的情况,必须使用while判断标记,用notifyAll唤醒线程。
	 * 
	 * 为什么使用notifyAll,因为需要唤醒对方线程,
	 * 只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
	 */
	public static void main(String[] args) {
		Resource1 res=new Resource1();
		new Thread(new Producer(res)).start();
		new Thread(new Producer(res)).start();
		new Thread(new Consumer(res)).start();
		new Thread(new Consumer(res)).start();//如果是多个线程消费,就有可能发生,生产者生产一个,不同消费者消费同一个产品的情况;
		                                      //或者生产者生产两次,消费者只消费了一次。

	}

}
class Resource1{
	private String name;
	private int count = 1;
	private boolean flag=false;
	/**
	 * 在这里分析一下:t1、t2是生产者线程,t3、t4是消费者线程。
	 * 假设t1先获取到cpu执行权,
	 * 一,t1进入set方法,判断if(flag)为false,t1生产一个商品,把flag置为true,t1接着又循环进入判断if(flag)为true,t1进入等待状态,放弃执行资格。
	 * 二,这时,假设t2获得cpu执行权,t2进入set方法,判断if(flag)为true,进入等待状态,放弃执行资格。
	 * 三,t3进入out方法,判断flag为true,消费一个商品,把flag置为false,notify唤醒t1,
	 *     但是t3才有执行权,t3判断if(flag)为false,t3进入等待,放弃资格。
	 * 四,t4进入out方法,进入等待,放弃资格。
	 * 五,此时t1是唤醒状态,生产一个商品,flag置为true,notify唤醒t2,t1仍有执行权,t1判断if(flag)为true,进入等待状态,放弃资格。
	 * 六,此时,t2处于唤醒状态,t2继续往下执行,而不会去判断if(flag)了,直接又生产一个商品,这就导致生产了两个商品。t2把flag置为true,notify唤醒t3,
	 *     t3这时只消费了t2生产的商品,t1生产的商品就没有消费了。
	 * 原因就是在线程唤醒后,没有再去判断flag,把if改为while就会实现唤醒后还会判断flag了。
	 * 但是这样,会发生几个线程都会等待。
	 * 这时就可以使用notifyAll方法解决问题。
	 * 
	 */
	public synchronized void set(String name){
//		if(flag){
		while(flag){//用while判断后,用this.notify唤醒本方,而不能唤醒对方,所以会导致都处于等待状态。
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.name=name+"--"+count++;
		System.out.println(Thread.currentThread().getName()+"...生产者"+this.name);
		flag=true;
//		this.notify();
		this.notifyAll();//notifyAll唤醒在此对象监视器上等待的所有线程
	}
	public synchronized void out(){
//		if(!flag){
		while(!flag){
			try {
				wait();//这里this省略了
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+"...消费者"+this.name);
		flag=false;
//		this.notify();
		this.notifyAll();
	}
}
class Producer implements Runnable{
	private Resource1 res;
	Producer(Resource1 res){
		this.res=res;
	}
	public void run(){
		while(true){
			res.set("商品");
		}
	}
}
class Consumer implements Runnable{

	private Resource1 res;
	Consumer(Resource1 res){
		this.res=res;
	}
	public void run(){
		while(true){
			res.out();
		}
	}
}


 

你可能感兴趣的:(多线程,生产者和消费者,线程通信,notify,notifyAll)