浅谈Java线程间通信方式

目录
  • 1.volatile和synchronized关键字
  • 2.等待/通知机制
  • 3.管道输入/输出流
  • 4.join()方法
  • 5.ThreadLocal()方法
  • 总结

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

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

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

在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信,在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是强引用,所以使用完毕后要及时清理(尤其使用线程池时)。

总结

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

(0)

相关推荐

  • 深入理解Java 线程通信

    当线程在系统内运行时,线程的调度具有一定的透明性,程序通常无法准确控制线程的轮换执行,但 Java 也提供了一些机制来保证线程协调运行. 传统的线程通信 假设现在系统中有两个线程,这两个线程分别代表存款者和取钱者--现在假设系统有一种特殊的要求,系统要求存款者和取钱者不断地重复存款.取钱的动作,而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱.不允许存款者连续两次存钱,也不允许取钱者连续两次取钱. 为了实现这种功能,可以借助于 Object 类提供的 wait(). notify()

  • 浅析Java中如何实现线程之间通信

    正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了. 本文涉及到的知识点:thread.join(), object.wait(), object.notify(), CountdownLatch, CyclicBarrier, FutureTask, Callable 等. 下面我从几个例子作为切入点来讲解下 Java 里有哪些方法来实现线程间通信. 如何让两个线程依次执行? 那如何让两个线程按照指定方式有序交叉运

  • Java多线程通信实现方式详解

    这篇文章主要介绍了Java多线程通信实现方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 线程通信的方式: 1.共享变量 线程间通信可以通过发送信号,发送信号的一个简单方式是在共享对象的变量里设置信号值.线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步代码块里读取hasDataToProcess这个成员变量.这个简单的例子使用了一个持有信号的对象,并提供了set和get方法. pu

  • java多线程编程学习(线程间通信)

    一.概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一.可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督. 二.等待/通知机制 1."wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行.用一个厨师和服务员的交互来说明: (1) 服务员取到菜的时间取决于厨师,所以服务员就有&

  • java多线程编程之管道通信详解

    上一章节讲了wait/notify通信,这一节我们来探讨使用管道进行通信. java中提供了IO流使我们很方便的对数据进行操作,pipeStream是一种特殊的流,用于不同线程间直接传送数据.一个线程将数据发送到输出管道,另一个线程从输入管道读取数据.通过管道实现通信不需要借助临时文件这类东西. java中提供了四个类使得线程间可以通信: ①字节流:PipeInputStream,PipedOutputStream ②字符流:PipedReader,PipedWriter 下面我们看看字节流的实

  • Java并发编程之线程间的通信

    一.概念简介 1.线程通信 在操作系统中,线程是个独立的个体,但是在线程执行过程中,如果处理同一个业务逻辑,可能会产生资源争抢,导致并发问题,通常使用互斥锁来控制该逻辑.但是在还有这样一类场景,任务执行是有顺序控制的,例如常见的报表数据生成: 启动数据分析任务,生成报表数据: 报表数据存入指定位置数据容器: 通知数据搬运任务,把数据写入报表库: 该场景在相对复杂的系统中非常常见,如果基于多线程来描述该过程,则需要线程之间通信协作,才能有条不紊的处理该场景业务. 2.等待通知机制 如上的业务场景,

  • 浅谈Java线程间通信方式

    目录 1.volatile和synchronized关键字 2.等待/通知机制 3.管道输入/输出流 4.join()方法 5.ThreadLocal()方法 总结 线程间通信方式有两种:共享内存和消息传递. 不同进程间线程通信等同于进程间通信,同一进程间可用共享内存实现. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信,典型的共享内存通信方式就是通过共享对象进行通信. 在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送

  • 浅谈Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.先来我们来看下相关定义: wait() :调用该方法的线程进入WATTING状态,只有等待另外线程的通知或中断才会返回,调用wait()方法后,会释放对象的锁. wait(long):超时等待最多long毫秒,如果没有通知就超时返回. notify() :通知一个在对象上等待的线程,使其从wait()方法返回,而返回的前提

  • 浅谈java线程中生产者与消费者的问题

    一.概念 生产者与消费者问题是一个金典的多线程协作的问题.生产者负责生产产品,并将产品存放到仓库:消费者从仓库中获取产品并消费.当仓库满时,生产者必须停止生产,直到仓库有位置存放产品:当仓库空时,消费者必须停止消费,直到仓库中有产品. 解决生产者/消费者问题主要用到如下几个技术:1.用线程模拟生产者,在run方法中不断地往仓库中存放产品.2.用线程模拟消费者,在run方法中不断地从仓库中获取产品.3  . 仓库类保存产品,当产品数量为0时,调用wait方法,使得当前消费者线程进入等待状态,当有新

  • 浅谈Java线程池是如何运行的

    异步编程工具在Android开发中目前最被推荐的就是Kotlin协程,在引入Kotlin协程机制前,除了响应式扩展(RxJava)兼任异步编程工具外,Java API中线程与线程池就是最重要异步编程手段.而对于Android平台的Kotlin协程实现来说,依然使用的是线程池来作为任务执行的载体,所以可以将Android平台的Kotlin协程简单的理解是对线程池的一种高度封装. Executors.newFixedThreadPool(10).asCoroutineDispatcher() Dis

  • 浅谈JAVA 线程状态中可能存在的一些误区

    BLOCKED 和 WAITING 的区别 BLOCKED 和 WAITING 两种状态从结果上来看,都是线程暂停,不会占用 CPU 资源,不过还是有一些区别的 BLOCKED 等待 Monitor 锁的阻塞线程的线程状态,处于阻塞状态的线程正在等待 Monitor 锁进入 synchronized   Block 或者 Method ,或者在调用 Object.wait 后重新进入同步块/方法.简单的说,就是线程等待 synchronized 形式的锁时的状态 下面这段代码中, t1 在等待

  • 浅谈Java线程池的7大核心参数

    前言 java中经常需要用到多线程来处理一些业务,我不建议单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源.线程上下文切换问题. 同时创建过多的线程也可能引发资源耗尽的风险,这个时候引入线程池比较合理,方便线程任务的管理. java中涉及到线程池的相关类均在jdk1.5开始的java.util.concurrent包中,涉及到的几个核心类及接口包括: Executor.Executors.ExecutorService.ThreadPoolE

  • 浅谈java线程状态与线程安全解析

    目录 1.线程的几种状态 1.1 线程的状态 1.2 线程状态的转移 2.有关线程安全问题 2.1 一个简单的例子 2.2 造成线程不安全的原因 1.线程的几种状态 1.1 线程的状态 以下就是我们线程所有的状态和意义: NEW 已经创建Thread但未创建线程 RUNNABLE 可工作的. 又可以分成正在工作中和即将开始工作 BLOCKED 等待锁(阻塞状态) WAITING 调用wati方法(阻塞状态) TIMED_WAITING 调用sleep方法(阻塞状态) TERMINATED 系统线

  • 浅谈java线程join方法使用方法

    本博客简介介绍一下java线程的join方法,join方法是实现线程同步,可以将原本并行执行的多线程方法变成串行执行的 如图所示代码,是并行执行的 public class ThreadTest { //private static final Long count = 10000L; public static void main(String[] args){ long base = System.currentTimeMillis(); try { ThreadJoin t1 = new

  • 浅谈Java线程Thread之interrupt中断解析

    这一篇我们说说Java线程Thread的interrupt中断机制. 中断线程 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡.还是等待新的任务或是继续运行至下一步,就取决于这个程序本身.线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断标示值是否为true).它并不像stop方法那样会中断一个正在运行的线程. 判断线程是否被中断 判断某个线程是否已被发送过中断请求,请使用Thread.currentThr

  • 浅谈Java线程Thread.join方法解析

    join字面上是加入的意思,我们先看看join方法的解释和实现. /** * Waits for this thread to die. * 调用方线程(调用join方法的线程)执行等待操作,直到被调用的线程(join方法所属的线程)结束,再被唤醒 * <p> An invocation of this method behaves in exactly the same * way as the invocation * * * @throws InterruptedException *

随机推荐