线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体。线程间的通信就是成为整体的必用方案之一,使线程间进行通信后,系统之间的交互性会更强大。
使用wait/notify(等待/通知机制)实现线程间的通信。
wait使线程停止运行,而notify使停止的线程继续运行。
方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是object类的方法,该方法用来将当前线程置入“预执行队列” 中,并且在wait()所在代码行处停止执行,直到接到通知或被中断为止。
方法notify()要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁。如果调用没有持有适当的锁,也会抛出IllegalMonitorStateException。
notify()方法可以随机唤醒等待队列中等待同一个共享资源的一个线程,并使该线程退出等待队列,进入可运行状态,也就是notify()方法仅通知一个线程。
notifyAll()方法可以使所有正在等待队列中等待同一个共享资源的“全部”线程从等待状态退出,进入可运行状态。此时,优先级最高的那个线程最先执行,但也可能随机执行,这要取决于JVM虚拟机的实现。
线程状态切换示意图:
每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,反之,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒。
当方法wait()被执行后,锁被自动释放,但执行完notify()方法,锁却不自动释放。
当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptException异常。
方法wait(long):等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。
变量值得共享可以使用public static 变量的形式,所有的线程都使用同一个public static变量。如果想实现每一个线程都有自己的共享变量就需要用到类ThreadLocal。
类ThreadLocal主要解决的就是每个线程绑定自己的值。
使用InheritableThreadLocal类可以让子线程从父线程中取得的值。使用InheritableThreadLocal类需要注意的是,如果子线程在取得值得同时,主线程将InheritableThreadLocal中的值进行更改,那么子线程取到的值还是旧值。