好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

浅谈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 ,前两种面向字节,而后两种面向字符。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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是强引用,所以使用完毕后要及时清理(尤其使用线程池时)。

总结

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

原文链接:https://blog.csdn.net/weixin_46263596/article/details/121035160

查看更多关于浅谈Java线程间通信方式的详细内容...

  阅读:13次