浅谈Java线程间通信方式

 更新时间:2021年11月02日 14:45:05   作者:平平无奇小叶同学  
这篇文章主要为大家详细介绍了Java线程间的通信方式,以代码结合文字的方式来讨论线程间的通信,感兴趣的朋友可以参考一下

线程间通信方式有两种:共享内存消息传递。

不同进程间线程通信等同于进程间通信,同一进程间可用共享内存实现。

在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信,典型的共享内存通信方式就是通过共享对象进行通信。

在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信,在java中典型的消息传递方式就是wait()和notify()。

详细来说,线程通信有以下几种方式:

1.volatile和synchronized关键字

volatile关键字保证了共享变量的可见性,任何线程需要读取时都要到内存中读取(确保获得最新值)。synchronized关键字确保只能同时有一个线程访问方法或者变量,保证了线程访问的可见性和排他性。

synchronized底层是基于监视器(Monitor)的获取,每个对象都有自己的监视器,线程必须获得监视器才能继续执行内容。

在这里插入图片描述

2.等待/通知机制

等待/通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B 调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而 执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的 关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作(注意此机制要和锁一起使用,调用notify的线程执行完后释放了锁新唤醒线程才能运行)。

在这里插入图片描述

3.管道输入/输出流

管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要 用于线程之间的数据传输,而传输的媒介为内存。

管道输入/输出流主要包括了如下4种具体实现:PipedOutputStreamPipedInputStream PipedReaderPipedWriter,前两种面向字节,而后两种面向字符。

    public class Piped {
        public static void main(String[] args) throws Exception {
            PipedWriter out = new PipedWriter();
            PipedReader in = new PipedReader(); // 将输出流和输入流进行连接,否则在使用时会抛出IOException
            out.connect(in);
            Thread printThread = new Thread(new Print(in), "PrintThread");
            printThread.start();
            int receive = 0;
            try {
                while ((receive = System.in.read()) != -1) {
                    out.write(receive);
                }
            } finally {
                out.close();
            }
        }
        static class Print implements Runnable {
            private PipedReader in;
            public Print(PipedReader in) {
                this.in = in;
            }
            public void run() {
                int receive = 0;
                try {
                    while ((receive = in.read()) != -1) {
                        System.out.print((char) receive);
                    }
                } catch (IOException ex) {
                }
            }
        }
    }

4.join()方法

如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才 从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时 时间里没有终止,那么将会从该超时方法中返回。

每个线程终止的前提是前驱线程的终止,每个线程等待前驱线程终止后,才从join()方法返回,这里涉及了等待/通知机制(等待前驱线程结束,接收前驱线程结束通知)。

5.ThreadLocal()方法

ThreadLocal,即线程本地变量(每个线程都有自己唯一的一个哦),是一个以ThreadLocal对象为键、任意对象为值的存储结构。底层是一个ThreadLocalMap来存储信息,key是弱引用,value是强引用,所以使用完毕后要及时清理(尤其使用线程池时)。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • Java SpringMVC实现国际化整合案例分析(i18n)

    Java SpringMVC实现国际化整合案例分析(i18n)

    本篇文章主要介绍了Java SpringMVC实现国际化整合案例分析(i18n),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 基于SpringBoot实现图片上传与显示

    基于SpringBoot实现图片上传与显示

    这篇文章主要为大家详细介绍了基于SpringBoot实现图片上传与显示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • springboot过滤器和拦截器的实例代码

    springboot过滤器和拦截器的实例代码

    这篇文章主要介绍了springboot过滤器和拦截器的实例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • IDEA 设置显示内存的使用情况和内存回收的方法

    IDEA 设置显示内存的使用情况和内存回收的方法

    这篇文章主要介绍了IDEA 设置显示内存的使用情况和内存回收的方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • java代码抓取网页邮箱的实现方法

    java代码抓取网页邮箱的实现方法

    下面小编就为大家带来一篇java代码抓取网页邮箱的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • java中InputStream转为MultipartFile的解决方案

    java中InputStream转为MultipartFile的解决方案

    这篇文章主要介绍了java中InputStream转为MultipartFile的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • SpringBoot全局处理统一返回类型方式

    SpringBoot全局处理统一返回类型方式

    这篇文章主要介绍了SpringBoot全局处理统一返回类型方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 教你bat脚本一键配置java开发环境

    教你bat脚本一键配置java开发环境

    公司新入职一名员工,项目经理让我安排新人工作,首先需要对java开发相关环境进行配置安装,但时常会因为安装配置不到位或者操作错误导致时间的浪费,所以在空余时间收集了一系列软件的免安装版本,感兴趣的朋友一起看看吧
    2021-12-12
  • Hibernate之环境搭建及demo分享

    Hibernate之环境搭建及demo分享

    下面小编就为大家分享一篇Hibernate之环境搭建及demo,具有很好的参考价值,希望对大家有所帮助
    2017-11-11
  • Java Feign微服务接口调用方法详细讲解

    Java Feign微服务接口调用方法详细讲解

    现如今微服务架构十分流行,而采用微服务构建系统也会带来更清晰的业务划分和可扩展性。java如果使用微服务就离不开springcloud,我这里是把服务注册到nacos上,各个服务之间的调用使用feign
    2023-01-01

最新评论