【线程间通信:代码示例:分析问题原因:修正代码】

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

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();

    }

}
终身学习者
原文地址:https://www.cnblogs.com/zuixinxian/p/9572382.html