浅谈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种具体实现:PipedOutputStream
、PipedInputStream
、 PipedReader
和PipedWriter
,前两种面向字节,而后两种面向字符。
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是强引用,所以使用完毕后要及时清理(尤其使用线程池时)。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
相关文章
ServletWebServerApplicationContext创建Web容器Tomcat示例
这篇文章主要为大家介绍了ServletWebServerApplicationContext创建Web容器Tomcat示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-03-03构建springboot自动生成mapper文件和dao接口项目的步骤和配置方法
这篇文章主要介绍了构建springboot自动生成mapper文件和dao接口项目的步骤和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-05-05Java Web使用简单的批处理操作(记事本+Tomcat)
这篇文章主要介绍了Java Web使用简单的批处理操作 ,需要的朋友可以参考下2014-10-10
最新评论