zoukankan      html  css  js  c++  java
  • 【线程间通信:代码示例:分析问题原因:修正代码】

    针对同一个资源的操作有不同种类的线程:生产线程和消费线程

    package com.test;
    
    public class Student {
    
        String name;
        int age;
    
    }
    package com.test;
    
    public class SetThread implements Runnable {
    
        private Student s;
    
        public SetThread(Student s){
            this.s = s;
        }
        @Override
        public void run() {
            s.name="叶胖子";
            s.age=27;
        }
    
    }
    package com.test;
    
    public class GetThread implements Runnable {
    
        private Student s;
    
        public GetThread(Student s){
            this.s = s;
        }
    
        @Override
        public void run() {
            System.out.println(s.name+"---"+s.age);
        }
    }
    package com.test;
    
    public class StudentTest {
    
        public static void main(String[] args) {
    
            Student s = new Student();
    
            SetThread st = new SetThread(s);
            GetThread gt = new GetThread(s);
    
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(gt);
    
            t1.start();
            t2.start();
    
        }
    
    }

    执行结果:

    null---0

    分析:

      资源类:Student

      设置学生数据:SetThread(生产者)

      获取学生数据:GetThread(消费者)

      测试类:StudentTest

    问题一:执行测试类,发现输出结果是null---0

      原因:我们在每个线程中都创建了新的资源,而我们要求的是设置和获取的资源应该是同一个学生对象。

      解决办法:在外界把这个对象创建出来,通过构造方法传递给生产者和消费者。

    问题二:为了数据的效果好一些,我如果加入了循环和判断,给出不同的值,这时会出现新的问题

      A:同一个数据出现多次

      B:姓名和年龄不匹配

      原因:A:同一个数据出现多次,CPU的一点点时间片的执行权,就足够你执行很多次。

         B:姓名和年龄不匹配,是因为线程运行的随机性。

      线程安全问题:

        A:是否是多线程环境(是)

        B:是否有共享数据(是)

        C:是否有多条语句操作共享数据(是)

      解决方案:加锁

      注意:A:不同种类的线程都要加锁

            B:不同种类的线程加的锁必须是同一把

    实现线程安全后的代码如下:

    package com.test;
    
    public class Student {
    
        String name;
        int age;
    
    }
    package com.test;
    
    public class SetThread implements Runnable {
    
        private Student s;
        private int x = 0;
    
        public SetThread(Student s){
            this.s = s;
        }
        @Override
        public void run() {
            while(true){
                synchronized (s){
                    if(x%2==0){
                        s.name="叶胖子";
                        s.age=30;
                    }else{
                        s.name="王瘦子";
                        s.age=31;
                    }
                    x++;
                }
            }
        }
    
    }
    package com.test;
    
    public class GetThread implements Runnable {
    
        private Student s;
    
        public GetThread(Student s){
            this.s = s;
        }
    
        @Override
        public void run() {
            while (true){
                synchronized(s){
                    System.out.println(s.name+"---"+s.age);
                }
            }
        }
    
    }
    package com.test;
    
    public class StudentTest {
    
        public static void main(String[] args) {
    
            Student s = new Student();
    
            SetThread st = new SetThread(s);
            GetThread gt = new GetThread(s);
    
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(gt);
    
            t1.start();
            t2.start();
    
        }
    
    }
    终身学习者
  • 相关阅读:
    利用 Remoting 实现异步队列机制
    JsonHelper
    吐血推荐"泛绿色编程工具": EditPlus 已于 20100714 升级到 v3.12(602)
    以 Console 方式运行、调试、编译 .Net 编写的 Windows 服务
    CompressHelper
    支持掩码输入的 .Net 2.0 Console 可用于使用掩码回显 password 的字符
    20080411 正式版 Microsoft Visual Studio International Pack 1.0 处理汉字、拼音、笔画转换
    CryptoHelper
    C++之String的find方法,查找一个字符串在另一个字符串的什么位置;leveldb字符串转数字解析办法
    Linux线程之线程池、高并发、线程数 C/C++ pthread 函数库
  • 原文地址:https://www.cnblogs.com/zuixinxian/p/9572382.html
Copyright © 2011-2022 走看看