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

来源:互联网 发布:2016大数据教程百度云 编辑:程序博客网 时间:2024/05/16 08:03


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;}// 商品IDprivate 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 blocke.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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 blocke.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 stubResource 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;}// 商品IDprivate 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 blocke.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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 blocke.printStackTrace();}}System.out.println("消费名称:" + Thread.currentThread().getName()+ "以消费商品为:" + this.name);// 无商品hasGoods = false;// 想通知生产线程来消费// notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁condition.signalAll();} finally {lock.unlock();}}}


阅读全文
0 0
原创粉丝点击