1.什么是线程间的通信
通信,顾名思义就是一种通知交通的方式,在多线程的环境下,如果各个线程之间可以互相通信的话,可以很好地提高工作效率,提高CPU的利用率。
Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。Java内存模型的抽象示意如图3-1所示
从图3-1来看,如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。
1)线程A把本地内存A中更新过的共享变量刷新到主内存中去。
2)线程B到主内存中去读取线程A之前已更新过的共享变量
2.线程间常用的通信方式
多线程间的通信一般采取等待/通知机制进行实现,即Object类中的wait()和notify()方法实现的,一个是等待,一个是通知。其实就像我们平时去营业厅办理业务一样,我们要先取号,然后就开始等待,等到听到叫我们号的时候,我们再过去办理业务。
- Java中等待/通知机制的实现
- 如上面所说的,wait()和notify()这两个方法都是Object类中的方法,之所以是超类的方法,其实是因为之前我们说过任何对象都可以作为锁,而这两个方法都是由锁调用的,所以很自然地就可以理解为什么这两个方法是属于超类的。
- wait方法:
- 作用是使当前执行代码的线程进行等待,该方法会将该线程放入”等待队列“中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。
- 在调用 wait() 之前,线程必须获得该对象级别锁,即只能在同步方法或同步块中调用 wait() 方法。
- wait() 是释放锁的,即在执行到 wait() 方法之后,当前线程会释放锁,当从 wait() 方法返回前,线程与其他线程竞争重新获得锁
- 此外,还有带一个参数的wait(long),表示在等待一段时间内,如果没有唤醒线程,则会自动唤醒。当然,在这段时间内,也可以由其他线程唤醒。
- notify方法:
- 和 wait() 方法一样, notify() 方法也要在同步块或同步方法中调用,即在调用前,线程也必须获得该对象的对象级别锁。
- 该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出其中一个是wait状态的线程