【温故知新】-JUC包梳理

1.概念

1.1JUC是什么

java.util.concurrent包的简称,提供了一系列支持多线程编程的工具类,涉及多线程编程就绕不开JUC,JUC中提供的各种API也是面试经常会被问到.

1.2JUC底层AQS原理

值得一提的是JUC提供的大部分功能都是借助AQS实现的,AQS全称AbstractQueuedSynchronizer,直译为抽象的队列同步器,底层通过volatile关键字修饰state,加上CAS操作修改state来实现锁的获取(state由0递增为1),重入(state递增),锁的释放(最终state变为0),配合CLH队列实现锁的公平/非公平,以及独占/共享. CLH队列是一个双端双向链表(FIFO),当一个线程尝试获取锁成功则直接返回,失败则会被加入CLH队列的尾部,等待时机,重新获取锁.

2.工具

2.1线程池

线程池,基本上用到多线程的地方都会用,阿里代码规范中也强制要求线程资源必须从线程池中获取,不允许手动new(写demo,测试用随意),Executors类提供了几个静态方法创建线程池,不过也仅适合写一些demo和测试的时候用,依然不推荐使用,一些场景下容易榨干系统资源,正确的姿势是通过ThreadPoolExecutor(args)来创建,并且尽量指定合理的线程数量,存活时间,以及取一个有意义的线程名,比如该线程池是用于订单模块的线程池,可以在线程名加个Order前缀,这样如果线程异常了,可以快速定位问题.

线程池底层的原理如图(懒得画,网图)

【温故知新】-JUC包梳理_第1张图片

2.2CountDownLatch

线程计数器,当指定计数递减为0时,才会继续运行,否则主线程可被await阻塞,适用于多个线程协调完成某件事情时,需要多个线程全部完成才认为此事做完的场景,底层也是CLH队列,state的值就是CountDownLatch构造时传入的值,跟锁的重入时的释放有点类似,state递减,直到为0时,解除阻塞.

2.3CyclicBarrier

CyclicBarrier可以当作是加强版的CountDownLatch,功能上与CountDownLatch一样,但它可以循环多次使用.

2.4Semphare

信号量,可以指定一件事情同时最多允许多少个线程并发去做,可以对某件任务的最大线程参与数量作控制.

2.5ReentrantLock

可重入悲观锁,支持公平非公平两种模式,我在锁专题有专门梳理,这里不再赘述.

2.6Queue

JUC提供了多种队列:

ArrayBlockingQueue:基于数组实现的阻塞队列,长度需要指定,是有界队列

ConcurrentLinkedQueue:并发非阻塞队列,性能较好,FIFO.

DelayQueue:延迟队列,需要指定延迟时间,当指定时间到了,才能消费,适用场景比较多,比如下单后超过60秒未付款则关闭订单等类似这种需要延迟处理的场景...

PriorityBlockingQueue:基于优先级的阻塞队列,按照指定的排序规则消费数据,也有很多使用场景,比如优先让会员等级高的用户抢到某资源...

2.7Concurrent容器

CopyOnWriteArrayList:是ArrayList的并发版,不会出现CME,相比Vector直接加锁的方式,性能要高很多,它支持无锁并发读,当有数据写入时,会先将原数据拷贝一份,然后写入新数据,再将原引用指向新的数据.

ConcurrentHashMap:相比HashTable,不仅线程安全,而且性能有很大提升,在jdk1.7中是以分段锁的形式实现,在jdk1.8底层数据结构改为数组+链表+红黑树,同时并发控制改为cas+synchronized控制

ConcurrentSkipListMap:是TreeMap的线程安全版本,保证了key的有序性,查询时间复杂度为log(n),与并发量无关,所以在超高并发下性能要优于ConcurrentHashMap

ConcurrentSkipListSet:ConcurrentSkipListMap的免value版本,没啥好说的了,一般不用,因为它能做的用redis都能做,而且性能更好,通常被用来排序.

 

 

你可能感兴趣的:(【温故知新】,【java进阶】-,多线程,JUC,AQS,CLH,Java并发,多线程)