zoukankan      html  css  js  c++  java
  • 生产者消费者_测试

    /*
     * 模拟生产者和消费者:
     *     思路:
     *         资源类:包子类
     *         生产者线程:SetThread
     *         消费者线程:GetThread
     *         测试类:Demo6
     *
     * 我们按照思路写出了代码,发现了有null和0这样的数据
     *      因为线程是抢占式争夺cpu的执行权的,有可能消费者线程先抢到了cpu的执行权,那么这个时候
     *     生产者线程还没有生产出来,所以就出现了null  和  0 这样的数据。
     *     很明显这样是不对的,应该是生产者先生产,然后消费者在消费。
     *
     *     为了让效果更明显一些,我加入循环和判断,给出不同的值
     * 结果又出现了新的问题:
     *         同一个包子被消费了多次
     *             因为cpu的一点点的执行权,就足够执行这个代码很多次。
     *          包子和价格不匹配了
     *             因为线程运行的随机性
     *
     * 说明存在线程安全问题:
     *         是否是多线程:是
     *         是否有共享数据:有
     *         是否有多条语句操作共享数据:有
     *
     *     解决方案:
     *         上锁
     *         注意:
     *             不同种类的线程都要加锁,而且必须是同一把锁    
     *
     * 线程安全问题通过加锁是解决了,但是还存在一个问题:
     *     如果是消费者先抢到了cpu的执行权,就会去消费,但是这个时候生产者还没有生产,消费者消费的数据就是默认值 null  和  0
     *     应该等生产者生产之后再消费。这样才有意义。
     *     如果生产者先抢到了执行权,就去生产,但是它生产完成后有肯能还拥有执行权,它就会继续生产,这个也是有问题的。
     *     应该是生产完后等消费者把它消费掉后,再继续生产。
     *
     * 正常的情况:
     *         生产者:
     *             先看是否有数据了,如果有,就等着消费者来消费。如果没有,就生产。生产完后通知消费者来消费包子。。。
     *         消费者:
     *             先看是否有数据,如果有,就消费。如果没有,就等待,通知生产者去生产。
     *
     * 为了解决这个问题,java就提供了一种机制:  等待唤醒机制。
     *
     *   等待唤醒机制:
     *       Object类中有3个方法:
     *           public final void wait()
                public final void notify()
                public final void notifyAll()
        为什么这几个方法不在Thread中?
            因为这个方法的调用是通过锁对象调用的,而我们同步代码块的锁对象可以是任意对象,
            所以,这些方法就定义再Object中。
     * */
    public class Demo6 {
        public static void main(String[] args) {
            //创建资源对象
            BaoZi bz = new BaoZi();
            //创建生产者和消费者
            SetThread st = new SetThread(bz);
            GetThread gt = new GetThread(bz);
            
            //创建线程
            Thread t1 = new Thread(st,"成产者");
            Thread t2 = new Thread(gt,"消费者");
            
            t2.setPriority(10);
            
            //启动线程
            t2.start();
            t1.start();
        }
    }
    package com.momo.demo;

    public class GetThread implements Runnable {
        private BaoZi bz;

        public GetThread(BaoZi bz) {
            this.bz = bz;
        }

        @Override
        public void run() {
            // BaoZi bz = new BaoZi();
            while (true) {
                synchronized (bz) {
                    System.out.println(bz.name + ":" + bz.price);
                    // System.out.println(Thread.currentThread().getName()+"消费了这个包子");
                }
            }
        }
    }
    package com.momo.demo;

    public class SetThread implements Runnable {
        private BaoZi bz;
        private int i = 0;

        public SetThread(BaoZi bz) {
            this.bz = bz;
        }

        @Override
        public void run() {
            // BaoZi bz = new BaoZi();
            while (true) {
                synchronized (bz) {

                    if (i % 2 == 0) {
                        bz.name = "肉包子";
                        bz.price = 2;
                        // System.out.println(Thread.currentThread().getName()+"生产了一个肉包子");
                    } else {
                        bz.name = "菜包子";
                        bz.price = 1;
                        // System.out.println(Thread.currentThread().getName()+"生产了一个菜包子");
                    }
                    // System.out.println(Thread.currentThread().getName()+"生产了一个包子");
                    i++;
                }
            }
        }

    }
    package com.momo.demo;

    public class BaoZi {
        String name;
        int price;
    }


    package com.momo.demo;
    /*
     * 模拟生产者和消费者:
     *     思路:
     *         资源类:包子类
     *         生产者线程:SetThread
     *         消费者线程:GetThread
     *         测试类:Demo6
     *
     * 我们按照思路写出了代码,发现了有null和0这样的数据
     *      因为线程是抢占式争夺cpu的执行权的,有可能消费者线程先抢到了cpu的执行权,那么这个时候
     *     生产者线程还没有生产出来,所以就出现了null  和  0 这样的数据。
     *     很明显这样是不对的,应该是生产者先生产,然后消费者在消费。
     *
     *     为了让效果更明显一些,我加入循环和判断,给出不同的值
     * 结果又出现了新的问题:
     *         同一个包子被消费了多次
     *             因为cpu的一点点的执行权,就足够执行这个代码很多次。
     *          包子和价格不匹配了
     *             因为线程运行的随机性
     *
     * 说明存在线程安全问题:
     *         是否是多线程:是
     *         是否有共享数据:有
     *         是否有多条语句操作共享数据:有
     *
     *     解决方案:
     *         上锁
     *         注意:
     *             不同种类的线程都要加锁,而且必须是同一把锁    
     *
     * 线程安全问题通过加锁是解决了,但是还存在一个问题:
     *     如果是消费者先抢到了cpu的执行权,就会去消费,但是这个时候生产者还没有生产,消费者消费的数据就是默认值 null  和  0
     *     应该等生产者生产之后再消费。这样才有意义。
     *     如果生产者先抢到了执行权,就去生产,但是它生产完成后有肯能还拥有执行权,它就会继续生产,这个也是有问题的。
     *     应该是生产完后等消费者把它消费掉后,再继续生产。
     *
     * 正常的情况:
     *         生产者:
     *             先看是否有数据了,如果有,就等着消费者来消费。如果没有,就生产。生产完后通知消费者来消费包子。。。
     *         消费者:
     *             先看是否有数据,如果有,就消费。如果没有,就等待,通知生产者去生产。
     *
     * 为了解决这个问题,java就提供了一种机制:  等待唤醒机制。
     *
     *   等待唤醒机制:
     *       Object类中有3个方法:
     *           public final void wait()
                public final void notify()
                public final void notifyAll()
        为什么这几个方法不在Thread中?
            因为这个方法的调用是通过锁对象调用的,而我们同步代码块的锁对象可以是任意对象,
            所以,这些方法就定义再Object中。
     * */
    public class Demo6 {
        public static void main(String[] args) {
            //创建资源对象
            BaoZi bz = new BaoZi();
            //创建生产者和消费者
            SetThread st = new SetThread(bz);
            GetThread gt = new GetThread(bz);
            
            //创建线程
            Thread t1 = new Thread(st,"成产者");
            Thread t2 = new Thread(gt,"消费者");
            
            t2.setPriority(10);
            
            //启动线程
            t2.start();
            t1.start();
        }
    }

    package com.momo.demo;

    public class GetThread implements Runnable {
        private BaoZi bz;

        public GetThread(BaoZi bz) {
            this.bz = bz;
        }

        @Override
        public void run() {
            // BaoZi bz = new BaoZi();
            while (true) {
                synchronized (bz) {
                    if(!bz.boo) {//false !false= true   !true = false  
                        try {
                            bz.wait();//t2就等待,会释放锁对象.将来醒来的时候,是从这里醒过来的。
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName()+":"+bz.name + ":" + bz.price);
                    // System.out.println(Thread.currentThread().getName()+"消费了这个包子");
                
                    //修改标记,唤醒线程
                    bz.boo = false;
                    bz.notify();//唤醒t1
                }
            }
        }
    }
    package com.momo.demo;

    public class SetThread implements Runnable {
        private BaoZi bz;
        private int i = 0;

        public SetThread(BaoZi bz) {
            this.bz = bz;
        }

        @Override
        public void run() {
            // BaoZi bz = new BaoZi();
            while (true) {
                synchronized (bz) {
                    //判断有没有
                    if(bz.boo) {//false   true   
                        try {
                            bz.wait();//t1等待,释放锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (i % 2 == 0) {
                        bz.name = "肉包子";
                        bz.price = 2;
                        
                         System.out.println(Thread.currentThread().getName()+"生产了一个肉包子");
                    } else {
                        bz.name = "菜包子";
                        bz.price = 1;
                         System.out.println(Thread.currentThread().getName()+"生产了一个菜包子");
                    }
                    // System.out.println(Thread.currentThread().getName()+"生产了一个包子");
                    i++;
                    //修改标记,唤醒线程
                    bz.boo = true;
                    bz.notify();    //唤醒t2,唤醒后并不是马上就执行了,还是要抢cpu的执行权。
                }
            }
        }

    }
    package com.momo.demo;

    public class BaoZi {
        String name;
        int price;
        boolean boo;//默认值是false,代表没有,如果是true了,就代表有了
    }

  • 相关阅读:
    JQuery MultiSelect(左右选择框)
    jquery隐藏table表格的某一列
    JS刷新页面的几种方法
    jQuery对select操作小结
    更新数据前jquery如何填充数据到表单域中
    hibernate中load和get方法的区别
    java项目常用 BaseDao BaseService
    js判断360浏览器 兼容模式IE版本
    vue 文本比较插件
    vue问题总结
  • 原文地址:https://www.cnblogs.com/ironman-yan/p/11191630.html
Copyright © 2011-2022 走看看