zoukankan      html  css  js  c++  java
  • Java多线程同步操作在升级

    Java同步问题再升级

    消费者与生成者

    问题引出

    • 多线程 生产者 消费者操作
      生产者负责信息内容的
    • 每当 生产者 生产完成一项完整的信息之后消费者从生成者取走信息
    • 如果生产者没有 生成完成 消费者等待生成完成 如果消费者没对数据消费 生成者要等待消费后 生成

    上代码

    class product implements Runnable {
        private Msg msg;
    
        public product(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                if (x % 2 == 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.setTitle("laowang");
                    this.msg.setContent("帅哥");
                } else {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.setTitle("laoliu");
                    this.msg.setContent("不是");
                }
            }
        }
    }
    
    class consumer implements Runnable {
        private Msg msg;
    
        public consumer(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.msg.getTitle() + ":" + this.msg.getContent());
            }
        }
    }
    
    class Msg {
        private String title;
    
        private String content;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
    }
    
    class tests {
        public static void main(String args[]) {
            Msg msg = new Msg();
            new Thread(new product(msg)).start();
            new Thread(new consumer(msg)).start();
        }
    
    }
    
    

    结果:

    laowang:帅哥
    laoliu:不是
    laoliu:不是
    laoliu:不是
    laowang:帅哥
    laoliu:帅哥
    laowang:帅哥
    laowang:帅哥
    laowang:帅哥
    laowang:不是
    

    发现数据 不同步了

    有重复生成 有重复取出的问题


    要想解决这个问题 最先解决的得是数据同步

    最简单的步骤就是使用synchronized 关键字

    msggetset 使用synchronized 关键字来构造

    上代码

    class product implements Runnable {
        private Msg msg;
    
        public product(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                if (x % 2 == 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.set("laowang","帅哥");
    
                } else {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.set("laoliu","不是帅哥");
    
                }
            }
        }
    }
    
    class consumer implements Runnable {
        private Msg msg;
    
        public consumer(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.msg.get());
            }
        }
    }
    
    class Msg {
        private String title;
    
        private String content;
    
        public synchronized void set(String title,String content) {
            this.title = title;
            this.content = content;
        }
        public synchronized String get() {
            return this.title + " - " + this.content;
        }
    }
    
    class tests {
        public static void main(String args[]) {
            Msg msg = new Msg();
            new Thread(new product(msg)).start();
            new Thread(new consumer(msg)).start();
        }
    
    }
    
    

    结果

    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    

    换一种实现?

    等待与唤醒操作

    在Object类有三种方法

    等待

    方法 备注
    wait() 死等
    wait(long timeout) 设置等待时间
    wait(long timeout, int nanos) 设置等待时间

    唤醒

    方法 备注
    notify() 唤醒第一个等待的
    notifyAll() 唤醒所有等待的
    package com.xiaowang;
    //多线程 生产者 消费者操作
    //生产者负责信息内容的
    //每当 生产者 生产完成一项完整的信息之后消费者从生成者取走信息
    //如果生产者没有 生成完成 消费者等待生成完成 如果消费者没对数据消费 生成者要等待消费后 生成
    
    class product implements Runnable {
        private Msg msg;
    
        public product(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                if (x % 2 == 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.set("laowang", "帅哥");
                } else {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.msg.set("laoliu", "不是帅哥");
                }
            }
        }
    }
    
    class consumer implements Runnable {
        private Msg msg;
    
        public consumer(Msg msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.msg.get());
            }
        }
    }
    
    class Msg {
        private String title;
    
        private String content;
    
        private boolean flag = true;//表示生成或者消费
    
        //flag = ture 允许生成
        //flag = false 运行消费
        public synchronized void set(String title, String content) {
            if (this.flag == false)
                try {
                    super.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            this.title = title;
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            this.content = content;
            this.flag = false;
            super.notify();
        }
    
        public synchronized String get() {
            if (this.flag == true) {//生成 还要等待
                try {
                    super.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            }
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            try {
                return this.title + " - " + this.content;
            } finally {
                this.flag = true;
                super.notify();
            }
    
        }
    }
    
    class tests {
        public static void main(String args[]) {
            Msg msg = new Msg();
            new Thread(new product(msg)).start();
            new Thread(new consumer(msg)).start();
        }
    
    }
    
    

    结果

    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    laoliu - 不是帅哥
    laowang - 帅哥
    

    这么做呢 就是增加了一条判断 判断当前的状态

    如果是生成线程 那么执行 生产线程 消费线程 等待 执行完唤醒次线程

    如果是消费线程 那么执行消费线程 生成线程 等待 执行完唤醒次线程

  • 相关阅读:
    Java 中的 volatile 关键字
    Java 隐式锁
    导致并发程序出问题的根本原因是什么?
    BZOJ_2434_[Noi2011]阿狸的打字机_AC自动机+出栈入栈序+树状数组
    BZOJ_5368_[Pkusc2018]真实排名_组合数
    CF上的3道小题(2)
    BZOJ_4199_[Noi2015]品酒大会_后缀自动机
    BZOJ_4566_[Haoi2016]找相同字符_后缀自动机
    BZOJ_3172_[Tjoi2013]单词_后缀自动机
    BZOJ_3998_[TJOI2015]弦论_后缀自动机
  • 原文地址:https://www.cnblogs.com/laowt/p/14546375.html
Copyright © 2011-2022 走看看