「JDK并发包基础」工具类详解

在写并发代码来提升性能时,会遵循某些最佳写法,而不是只用基础的wait和notify来控制复杂的流程。

Java.util.concurrent 包是专为 Java并发编程而设计的包,它下有很多编写好的工具,使用这些更高等的同步工具来编写代码,让我们的程序可以不费力气就得到优化。这些工具还在由一些优秀的工程师不断优化和完善,我们不必重复造轮子:

「JDK并发包基础」工具类详解

这篇文章讲述思维导图的工具类部分:

  1. ReentrantLock
  2. Condition
  3. Semaphore
  4. ReentrantReadWriteLock
  5. CountDownLatch
  6. CyclicBarrrer

1.ReentrantLock

1.1可重入

单线程可以重复进入,但必须重复退出。

「JDK并发包基础」工具类详解

一个线程拿到几个许可,就得释放几次,不然就造成线程等待,可在命令行查看等待的线程:jps -->jstack [ option ] pid

「JDK并发包基础」工具类详解

1.2可中断

长期线程在锁上等待问题,可以通过中断来解决:

「JDK并发包基础」工具类详解

「JDK并发包基础」工具类详解

可在命令行查看死锁:jps -->jstack [ option ] pid

「JDK并发包基础」工具类详解

1.3可限时

可限时也是一个避免永久等待构成死锁的解决方法:

「JDK并发包基础」工具类详解

1.4公平锁

先来的线程先得到锁,如果先来的线程一直拿不到锁,则会产生饥饿现象,公平锁虽然不会产生饥饿现象,排队会导致程序效率差。通过阅读ReentrantLock的源码发现:默认是非公平的,如果传入true,则是公平锁:

「JDK并发包基础」工具类详解

2.Condition

Condition与ReentrantLock的关系就类似于synchronized与Object.wait()/notify()。但是它与ReentrantLock结合使用,有await和signal与之对应.

利用Condition实现顺序执行:

「JDK并发包基础」工具类详解

3.Semaphore

翻译为信号量,允许多个线程进入临界区。说白了就是一个广义上的锁,相当于共享锁。比如信号量中我可以给它指定10个许可,每一个许可可以分配给若干个线程(当然一个线程也可以拿多个许可),拿到许可线程可以执行,如果许可分发完了,后面的线程就和锁一样去做等待。换句话说,当信号量等于1的时候,就相当于一把锁。

比如早期做限流时,我们系统是8核cpu,设置同时请求任务为8个,超过8个,可以用信号量让线程等待来加以控制:

4.ReentrantReadWriteLock

ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限, 它和后者都是单独的实现,彼此之间没有继承或实现的关系。读写锁可以很好的提高程序效率,如果读也加锁的话,每次只有一个线程能访问,不符合高并发程序设计。ReentrantLock和synchronized都属于阻塞的并行,会把线程挂起,而ReadWriteLock属于无等待的并发。

访问情况:读读共享,读写互斥,写写互斥

「JDK并发包基础」工具类详解

「JDK并发包基础」工具类详解

5.CountDownLatch

实际开发中经常用于监听某些初始化操作,等待初始化完成后,通知主线程继续工作,它相当于一个栅栏

「JDK并发包基础」工具类详解

测试代码:

「JDK并发包基础」工具类详解

6.CyclicBarrrer

倒数计时器。假设有一个场景:每个线程代表一个跑步运动员,当运动员都准备好后,才能一起出发,只要有一个人没有准备好,大家都等待:

「JDK并发包基础」工具类详解

系列:

【JDK并发包基础】线程池详解

【JDK并发包基础】并发容器详解

【JDK并发包基础】工具类详解


分享到:


相關文章: