010.多线程-线程间通信

版权声明:本文为博主原创文章,允许转载,请标明出处。

多线程之间的通信,其实就是多个线程同时操作(读+写)同一个资源。


安全问题: 当线程在读取资源的过程中,写线程操作了资源, 导致读线程读取的数据,一部分是写之前的数据,一部分是写之后的数据。


解决安全问题: 读线程和写线程使用同一把对象锁就好了。


code of demo:

package cn.qbz.thread;

/**
 * 线程间通信
 */
public class ConnectThreadTest {

    public static void main(String[] args) {
        Student student = new Student();
        ProduceTest produceTest = new ProduceTest(student);
        ConsumerTest consumerTest = new ConsumerTest(student);

        produceTest.start();
        consumerTest.start();

    }
}

class ProduceTest extends Thread {
    private Student student;

    public ProduceTest(Student student) {
        this.student = student;
    }

    @Override
    public void run() {
        int num = 1;
        while (true) {
            synchronized (student) {
                //如果可以生产,生产者生产
                if (student.getCanProduce()) {
                    if (num == 1) {
                        student.setAge(6);
                        student.setName("小王");
                        num = 0;
                    } else {
                        student.setName("老王");
                        student.setAge(99);
                        num = 1;
                    }

                    //重置生产者不可以生产
                    student.setCanProduce(false);
                }

                student.notifyAll();
                try {
                    student.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class ConsumerTest extends Thread {
    private Student student;

    public ConsumerTest(Student student) {
        this.student = student;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (student) {
                //如果不可以生产,进行消费
                if (!student.getCanProduce()) {
                    //重置生产者可以生产
                    student.setCanProduce(true);
                    System.out.println(student.toString());
                }

                student.notifyAll();
                try {
                    student.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Student {
    private String name;
    private Integer age;
    private Boolean canProduce = false;

    public Boolean getCanProduce() {
        return canProduce;
    }

    public void setCanProduce(Boolean canProduce) {
        this.canProduce = canProduce;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA技术站

shell学习五常用命令echo printf test

Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。命令格式:

923
来自专栏闵开慧

java反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的...

3546
来自专栏landv

C语言_基础代码_01

1903
来自专栏白驹过隙

Redis - set类型操作

38213
来自专栏zlmai的专栏

理解PHP的延迟静态绑定

static::中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名。这个东西可以实现在父类中,能够调用子类的方法和属性。

2182
来自专栏Python疯子

TebsorFlow基本语法

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invi...

1382
来自专栏西枫里博客

Python学习笔记九(变量作用域及内置函数和闭包函数)

在上次的学习中,初步认识了Python的自定义函数方式及变量参数。那么编程中的局部变量和全局变量应该是大多数语言的标配。Python中如果定义局部变量和全局变量...

832
来自专栏海天一树

小朋友学C语言(28):指针

(一)内存地址 #include <stdio.h> int main() { int var1 = 20; printf("变量var1的值为...

37510
来自专栏C/C++基础

Linux命令(4)——declare/typeset命令(builtin)

declare命令(别名typeset)属shell内建命令,用于申明shell变量并设置变量属性,或查看已定义的shell变量和函数。若不加上任何参数,则会显...

772
来自专栏开发与安全

从零开始学C++之模板(一):函数模板、函数模板特化、重载函数模板、非模板函数重载

一、引子 考虑求两数较大值函数max(a,b) 对于a,b的不同类型,都有相同的处理形式: return a < b ? b : a; 用已有方法解决:...

2000

扫码关注云+社区

领取腾讯云代金券