• 多线程模拟生产者和消费者模型


    模拟生产者一边生产数据,消费者一边取出数据,
    但以下代码会出现数据错位现象和重复生产,不符合我们的要求

    package com.wzy.java8.thread;
    class Info{ private String title; private String content; public void setContent(String content) { this.content = content; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public String getTitle() { return title; } } class Productor implements Runnable{ private Info info = null; public Productor(Info info){ this.info = info; } @Override public void run() { for(int i=0;i<100;i++) { if(i%2 == 0) { this.info.setTitle("偶数"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent("这是偶数"); }else{ this.info.setTitle("奇数"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent("这是奇数"); } } } } class Consumers implements Runnable{ private Info info = null; public Consumers(Info info) { this.info = info; } @Override public void run() { for(int i=0;i<100;i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(info.getTitle()+" "+info.getContent()); } } } public class Demo2 { public static void main(String[] args) { Info info = new Info(); Productor p = new Productor(info); Consumers c = new Consumers(info); new Thread(p).start(); new Thread(c).start(); } }
    奇数  这是偶数
    偶数  这是奇数
    奇数  这是偶数
    偶数  这是奇数
    奇数  这是偶数

    使用同步synchronized可以解决数据错位问题

    使用super.wait(),super.notify();可以解决重复生产问题

    思路:对于生产者:如果不可以生产,就休眠,等待正在取数据的消费者唤醒,被唤醒后,再生产,生产完成后唤醒消费者;消费者被唤醒后取数据,取完再唤醒生产者生产

    对于消费者:如果不可以取数据,就休眠,等待正在生产的生产者唤醒,被唤醒后,取数据,取完后再唤醒生产者,生产者被唤醒后,继续生产

    修改后代码如下:

    package com.wzy.java8.thread;
    
    class Info{
        private String title;
        private String content;
        private boolean flag = true;
        //true可以生产数据,不能取走数据
        //false可以取走数据,不能生产数据
        
        public synchronized void set(String title,String content) {
            if(this.flag == false) {
                //如果不能生产数据,就进行等待,等待其他线程唤醒它
                try {
                    super.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //被唤醒后,就进行生产
            this.title = title;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.content = content;
            this.flag = false;//生产完成,可以取数据了
            super.notify();//再唤醒其他线程取数据
        }
        public synchronized void get() {
            if(this.flag == true) {
                //如果不能取走数据,就进行等待,等待其他线程唤醒它
                try {
                    super.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //被唤醒后,就取走数据,并唤醒生产者
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.title +"  "+ this.content);
            this.flag = true;//已经取走数据了,可以生产了
            super.notify();
            
        }
        
    }
    class Productor implements Runnable{
        private Info info = null;
        public Productor(Info info){
            this.info = info;
        }
        @Override
        public void run() {
            for(int i=0;i<100;i++) {
                if(i%2 == 0) {
                    this.info.set("偶数", "这是偶数");
                }else{
                    this.info.set("奇数", "这是奇数");
                }
            }
        }
        
        
    }
    class Consumers implements Runnable{
        private Info info = null;
        public Consumers(Info info) {
            this.info = info;
        }
        @Override
        public void run() {
            for(int i=0;i<100;i++) {
                
                this.info.get();
            }
        }
        
    }
    public class Demo2 {
        /*
         * sleep() 是Thread的方法,休眠一定时间后会自动唤醒
         * wait() 是Object的方法,必须等待其他线程notify(),notifyAll()来唤醒
         * */
        
        public static void main(String[] args) {
            Info info = new Info();
            Productor p = new Productor(info);
            Consumers c = new Consumers(info);
            new Thread(p).start();
            new Thread(c).start();
            
        }
    }
    奇数  这是奇数
    偶数  这是偶数
    奇数  这是奇数
    偶数  这是偶数
    奇数  这是奇数
    偶数  这是偶数
    奇数  这是奇数
  • 相关阅读:
    实现treeview的动态加载
    sql server2000中使用convert来取得datetime数据类型样式(全)
    一道微软公司的面试题目的算法实现
    后台一行输入太多内容,使前台显示自动换行方法
    在js中刷新本页
    关于datediff函数的用法
    C#中StringBuilder类的使用(转)
    在字符串中使用引号("")等字符 需要用转义字符\ 例如
    常用的SQL和TSQL语句(一) (转)
    JS弹出窗口的运用与技巧(转)
  • 原文地址:https://www.cnblogs.com/wwzyy/p/5533961.html
Copyright © 2020-2023  润新知