Java多线程之线程通信(Demo演示) - Go语言中文社区

Java多线程之线程通信(Demo演示)


在上一篇博客 Java多线程之线程安全与线程同步(锁) 介绍一下线程安全与线程同步相关概念,在本篇博客将使用输入、输出Demo模拟线程通信。

线程通讯

1、何为线程通信

所谓线程通信,通俗的来说,就是多个线程之间需要进行信息交换,达到改变线程执行顺序、状态的目的。

2、线程通信Demo

Input进程负责往cache中写入信息,Output进程负责读出cache中的信息。
那么这就有几个逻辑问题了,只有Input进程往cache中写入了内容,Output进程才能进行读取信息,同样只有Output进程读出了信息,Input进程才能继续写入信息到cache。
在这里插入图片描述

代码初步实现:

package cn.hestyle.demo;

class MyCache{
    public String key;
    public String value;
    /**标记cache是否为空*/
    public boolean isEmpty = true;

    @Override
    public String toString() {
        return "MyCache{" +
                "key='" + key + ''' +
                ", value='" + value + ''' +
                ", isEmpty=" + isEmpty +
                '}';
    }
}

/**
 * 写入进程
 */
class InputThread extends Thread{
    private int count = 0;
    private MyCache myCache;

    public InputThread(MyCache myCache) {
        this.myCache = myCache;
    }

    @Override
    public void run() {
        //往myCache写入内容
        while (true) {
            if (myCache.isEmpty) {
                if (count == 0) {
                    myCache.key = "username";
                    myCache.value = "hestyle";
                } else {
                    myCache.key = "password";
                    myCache.value = "123456";
                }
                count = (count + 1) % 2;
                //写入了内容,标记cache不为空
                myCache.isEmpty = false;
            }
        }
    }
}

/**
 * 读出进程
 */
class OutputThread extends Thread{
    private MyCache myCache;

    public OutputThread(MyCache myCache) {
        this.myCache = myCache;
    }

    @Override
    public void run() {
        //往myCache读出内容
        while (true) {
            if (!myCache.isEmpty) {
                System.out.println(myCache);
                //读出了内容,标记cache为空
                myCache.isEmpty = true;
            }
        }
    }
}

/**
 * description: demo_01
 *
 * @author hestyle
 * @version 1.0
 * @className multi_thread_project_01->MultiThreadDemo01
 * @date 2020-02-09 15:35
 **/
public class MultiThreadDemo01 {
    public static void main(String[] args) {
        //创建一个公共cache
        MyCache myCache = new MyCache();
        //创建input、output进程
        InputThread inputThread = new InputThread(myCache);
        OutputThread outputThread = new OutputThread(myCache);
        //启动两个线程
        inputThread.start();
        outputThread.start();
    }
}

控制台输出:
在这里插入图片描述
这里的MyCache.isEmpty确实起到了Input进程Output进程交换信息的作用,实现了先写入再读取,读取后再写入的逻辑。

但是这个实现存在一个问题,就是非常耗CPU资源,Input进程不间断的去查询MyCache.isEmpty,判断是否可以写入信息,Output进程不间断的去查询MyCache.isEmpty,判断是否可以读取信息。

下面我们进一步完善逻辑,当Input进程写入后,通知Output进程读取,Output进程读取完后,接着就通知Input进程继续写入。

首先是引入锁的机制,对于MyCache的读、写只能有一个进程在进行。
关于锁、线程同步,可以参考上一篇博客
Java多线程之线程安全与线程同步(锁)

package cn.hestyle.demo;

class MyCache{
    public String key;
    public String value;
    /**标记cache是否为空*/
    public boolean isEmpty = true;

    @Override
    public String toString() {
        return "MyCache{" +
                "key='" + key + ''' +
                ", value='" + value + ''' +
                ", isEmpty=" + isEmpty +
                '}';
    }
}

/**
 * 写入进程
 */
class InputThread extends Thread{
    private int count = 0;
    private MyCache myCache;

    public InputThread(MyCache myCache) {
        this.myCache = myCache;
    }

    @Override
    public void run() {
        //往myCache写入内容
        while (true) {
        	//同步代码块,使用myCache作为锁
            synchronized (myCache) {
                if (!myCache.isEmpty) {
                    //如果myCache不为空,则input进程计入睡眠状态
                    try {
                        myCache.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (count == 0) {
                    myCache.key = "username";
                    myCache.value = "hestyle";
                } else {
                    myCache.key = "password";
                    myCache.value = "123456";
                }
                count = (count + 1) % 2;
                //写入了内容,标记cache不为空
                myCache.isEmpty = false;

                //写入完毕后,接着去通知正在等待读取的线程
                myCache.notifyAll();
            }

        }
    }
}

/**
 * 读出进程
 */
class OutputThread extends Thread{
    private MyCache myCache;

    public OutputThread(MyCache myCache) {
        this.myCache = myCache;
    }

    @Override
    public void run() {
        //往myCache读出内容
        while (true) {
        	//同步代码块,使用myCache作为锁
            synchronized (myCache) {
                if (myCache.isEmpty) {
                    //如果cache为空,则input进程进入等待状态
                    try {
                        myCache.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(myCache);
                //读出了内容,标记cache为空
                myCache.isEmpty = true;

                //input进程读取完毕后,接着去通知正在等待写入的进程
                myCache.notifyAll();
            }

        }
    }
}

/**
 * description: demo_01
 *
 * @author hestyle
 * @version 1.0
 * @className multi_thread_project_01->MultiThreadDemo01
 * @date 2020-02-09 15:35
 **/
public class MultiThreadDemo01 {
    public static void main(String[] args) {
        //创建一个公共cache
        MyCache myCache = new MyCache();
        //创建input、output进程
        InputThread inputThread = new InputThread(myCache);
        OutputThread outputThread = new OutputThread(myCache);
        //启动两个线程
        inputThread.start();
        outputThread.start();
    }
}

3、wait()、notify()、notifyAll()方法

wait()notify()notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。这三个方法最终调用的都是jvm级的native方法。

wait()方法:		 使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
notify()方法:	 通知某个正在等待这个对象的控制权的线程可以继续运行。
notifyAll()方法: 通知所有等待这个对象控制权的线程继续运行。
wait()sleep()color{red}wait()与sleep()区别:
1、对于sleep()方法,属于Thread类,而wait()方法,属于Object类中
2sleep()方法不会释放锁,wait()方法会释放锁。
	sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,
	但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
	在调用sleep()方法的过程中,线程不会释放对象锁。
 	而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,
 	只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

以上就是Java多线程之线程通信(Demo演示),主要是需要理解锁机制、线程五个状态相关内容。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_41855420/article/details/104241481
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢