多线程之生产消费者【经典例子java】


1.普通的生产消费者例子 

synchronized   JVM提供的多线程同步,在少量线程下,足够用来

this.wait()     线程等待

notify(),     JVM去随机唤醒一个线程,然后拿到锁 【不用竞争】

notifyall()  JVM去唤醒所有线程,然后竞争拿到锁需要竞争


多线程,小心死锁和没同步住数据



package com.test.thread.producerconsumer;

/**
 * 资源类
 * @author 汪兴安
 * 
 * 
 * bug 1.synchronized 方法中if this.wait();需要改成while this.wait(); 导致现象:多生产或多消费
 *     2.notify(); 必须换成成notifyAll() ,不然会死锁   导致现象:程序无限等待下去
 * 
 */
public class Resource {
	// 商品名称
	private String name;
	
	private  String names;
	
	
	public String getNames() {
		return names;
	}

	public void setNames(String names) {
		this.names = names;
	}

	// 商品ID
	private int id = 1;
	// 是否有商品
	private boolean hasGoods = false;
	

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	// 生产方法
	public synchronized void set(String name) {
		// 有商品
		while (hasGoods) {  //if  多线程用if,判断是作死
			try {
				//等等,已经有商品了,当然可以休息下
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	
		this.setName(name + "_" + id);
		
		id++;
		System.out.println("生产名称:" + Thread.currentThread().getName()
				+ "以生产商品为:" + this.name);
		// 有商品
		hasGoods = true;
		// 想通知消费线程来消费
		notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁

	}

	// 消费方法
	public synchronized void out() {
		// 没商品
		while (!hasGoods) {//if  多线程用if,判断是作死 应该放在while里面,因为如果是if的话,当被唤醒了,直接在if里面,往下执行了
			try {
				// 等等
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		System.out.println("消费名称:" + Thread.currentThread().getName()
				+ "以消费商品为:" + this.name);
		// 无商品
		hasGoods = false;
		// 想通知生产线程来消费
		notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁

	}

}



package com.test.thread.producerconsumer;

/**
 * 生产者 线程
 * @author 汪兴安
 *
 */
public class Producter implements Runnable {
	
	//持有对方的引用
	private Resource resource;
	public Producter(Resource resource)
	{
		this.resource=resource;
	
	}
	
	public void run()
	{
		//不断生产
		while(true)
		{
			resource.set(resource.getNames());
		}
	}

}





package com.test.thread.producerconsumer;

/**
 * 不断去消费 线程
 * @author 汪兴安
 *
 */
public class Customer implements Runnable {
	
	//持有对方的引用
	private Resource resource;
	public Customer(Resource resource)
	{
		this.resource=resource;
	}
	
	public void run()
	{
		//不断消费
		while(true)
		{
			resource.out();
		}
	}

}




package com.test.thread.producerconsumer;

/**
 * 多线程,就是要模拟多个请求才行
 * @author 汪兴安
 *
 */
public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Resource resource=new Resource();
		resource.setNames("iphone");
		
		Producter p=new Producter(resource);
		Customer c=new Customer(resource);
		new Thread(p).start();//一个工厂 生产
		new Thread(c).start(); //一群消费者
		new Thread(c).start();
		new Thread(c).start();
		new Thread(c).start();
		new Thread(c).start();
		new Thread(c).start();

	}

}




===================================华丽的分开了==============================================================================


其他类不变,就Resource变了,注释非常多,自己体会去吧


package com.test.thread.producerconsumer.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

/**
 * 资源类
 * 
 * @author 汪兴安
 * 
 *         Lock 优点:1.显示化,结构灵活,控制细粒度高,可以更高效
 * 
 * 
 * 
 *         synchronized的wait,nofity,notify是一套的,但Lock与condition可以组合多个,类似2分法,效率大大的提高
 * 
 *         bug 1.synchronized 方法中if this.wait();需要改成while this.wait();
 *         导致现象:多生产或多消费 2.notify(); 必须换成成notifyAll() ,不然会死锁 导致现象:程序无限等待下去
 * 
 */
public class Resource {
	// 商品名称
	private String name;

	private String names;

	public String getNames() {
		return names;
	}

	public void setNames(String names) {
		this.names = names;
	}

	// 商品ID
	private int id = 1;
	// 是否有商品
	private boolean hasGoods = false;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	// 显示的拿到锁对象
	private Lock lock = new ReentrantLock();
	// 获取锁的监控器对象-----更好隔离,拆分更细   与锁lock组合使用
	private Condition condition = lock.newCondition();
	// 获取锁的监控器对象-----更好隔离,拆分更细  与锁lock组合使用
	private Condition conditionOut = lock.newCondition();

	// 生产方法
	public void set(String name) {

		lock.lock();// 获取锁
		try {
			// 有商品
			while (hasGoods) { // if 多线程用if,判断是作死
				try {
					// 等等,已经有商品了,当然可以休息下
					// this.wait();
					condition.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			this.setName(name + "_" + id);

			id++;
			System.out.println("生产名称:" + Thread.currentThread().getName()
					+ "以生产商品为:" + this.name);
			// 有商品
			hasGoods = true;
			// 想通知消费线程来消费
			// notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
			conditionOut.signalAll();
		} finally {
			lock.unlock();
		}
	}

	// 消费方法
	public void out() {
		lock.lock();// 获取锁
		try {
			// 没商品
			while (!hasGoods) {// if 多线程用if,判断是作死
								// 应该放在while里面,因为如果是if的话,当被唤醒了,直接在if里面,往下执行了
				try {
					// 等等
					// this.wait();
					conditionOut.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			System.out.println("消费名称:" + Thread.currentThread().getName()
					+ "以消费商品为:" + this.name);
			// 无商品
			hasGoods = false;
			// 想通知生产线程来消费
			// notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
			condition.signalAll();
		} finally {
			lock.unlock();
		}
	}

}


你可能感兴趣的:(多线程之生产消费者【经典例子java】)