架构系列——线程通信的实现方式
目录
3.使用ReentrantLock创建Condition实现
一、什么是线程通信?
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能称为一个整体,线程间的通信就成为整体的必用方式之一。
当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时,还会使开发人员在处理线程任务的过程中有效的把控和监督。
二、线程通信的实现
1.使用volatile实现线程通信
如下列代码所示,list使用volatile修饰,利用volatile的可见性,当线程t1添加了5个元素的时候,t2得到通知!
弊端:需要不断地做while循环,影响性能!
2.使用wait/notify实现线程通信
wait和notify都是Object类的方法,而Object是所有类的父类,所以,java为所有的对象提供了这两个方法。
如下列代码所示,使用wait、notify结合synchronized实现线程通信。
弊端:不能实时获得锁,下面的代码运行之后,t1的循环做完t2才得到通知。
3.使用ReentrantLock创建Condition实现
Conditon中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll()。
这种方法跟 Object 的 wait和 notify 一样,不能实时获得锁,下面的代码运行之后,t1的循环做完t2才得到通知。
4.通过LockSupport实现线程通信
LockSupport
是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后肯定得有唤醒的方法。
线程通信主要用到两个函数:
park:英文意思为停车。我们如果把Thread看成一辆车的话,park就是让车停下
unpark:就是让车启动然后跑起来
弊端:需要知道被唤起的线程名字
5.使用CountDownLatch实现线程通信
CountDownLatch是concurrent包里面的一个类,CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。当每一个线程完成自己任务后,计数器的值就会减1。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以唤醒其他线程,继续执行接下来的任务。
await()函数:此函数将会使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
countDown函数:此函数将递减锁存器的计数,如果计数到达零,则释放所有等待的线程
如下列代码所示,t1中使用countDown方法之后,计数器会减到0,这时会立即唤醒t2线程,然后继续执行t2线程的代码
参考文献:
[1].CountDownLatch