JUC提供了几个并发工具,比方CountDownLatch,CycelicBarrier,Semaphore和Exchanger。
Semaphore
又名计数信号量,量初始并保护肯定数量的许可证,应用之前先要先取得一个许可,用完之后再开释一个许可。当然也能够逆向应用,在结构Semaphore的时候传入0个许可,执行某个操作后增加一个许可,而后再放行期待的线程。
信号量通常用于限度线程的数量来管制拜访某些资源,从而达到单机限流的目标。
Semaphore 也是基于AQS框架来实现的,Semaphore 也有偏心和非偏心之说,Semaphore 反对重入取得许可。
CountDownLatch
容许一个或多个线程期待其它线程实现操作。在初始化的时候给定 CountDownLatch 一个计数,调用await() 办法的线程会始终期待,其余线程执行完操作后调用countDown(),当计数减到0 ,调用await() 办法的线程被唤醒继续执行。
CountDownLatch没有减少计数的API,所以不能够重复使用,如果要用能够重置计数的,能够应用CyclicBarrier。
CountDownLatch能够用在多个线程同时去操作各自的逻辑,等都完结后再对立汇总等业务场景。
Exchanger
用于进行线程间的数据交换。它提供了一个同步点,在这个同步点,两个线程能够进行数据交换,次要是通过exchange()这个办法进行,如果第一个线程先执行exchange()办法,它会始终期待第二个线程也执行exchange()办法,当两个线程都达到同步点时,就能够将本线程生产出的数据传递给对方。
Exchanger外面有个外部类Node,应用了sun.misc.Contended注解进行润饰,因为最大的缓存行为128个字节,应用sun.misc.Contended来减少padding,能够使得任意两个可用Node不会再同一个缓存行中。
除了Exchanger外,其它三个类都是借助AQS实现的。
Exchanger源码可参考:源码剖析:Exchanger之数据交换器
JUC
JUC包下能够分为上面几类:
- atomic,根本类型、援用类型、累加器
- locks,读写锁、重入锁
- collections并发容器ConcurrentHashMap/ConcurrentSkipListMap及阻塞队列 BlockingQueue/CopyOnWriteArrayList
- executor执行框架与线程池,Future/Executor
- tools并发工具类,CountdownLatch/CyclicBarrier/Semaphore/Exchanger
AQS
1,state属性
AQS里有个重要的字段state,在不同的类里有着不同的含意:
- 基于state实现的排它锁ReentrantLock,state 值为1代表锁被占用,值为0时代表锁未被占用。
- 基于state实现的读写锁ReentrantReadWriteLock,state 被分成两局部,高16位记录读锁次数,低16位记录写锁次数。
- 基于state实现的信号量Semaphore,初始化一个state值,示意最大限度数,即能够做到容许最多N个线程同时运行,达到限流成果。
- 基于state实现的线程期待器CountDownLatch,初始化一个state值,state值为0时触发唤醒动作。
2,两个队列
AQS里有两个重要的队列:同步队列与期待队列。
- 同步队列:保护唤醒线程的队列,获取互斥锁失败时入队的线程。
- 期待队列:实现条件锁时用到的队列。调用await()的时候会开释锁,而后线程会退出到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点挪动到同步队列中,期待再次取得锁。
3,节点状态
AQS 定义了5个队列中节点状态:
- 值为0,初始化状态,示意以后节点在sync队列中,期待着获取锁。
- CANCELLED,值为1,示意以后的线程被勾销。
- SIGNAL,值为-1,示意以后节点的后继节点蕴含的线程须要运行,也就是unpark。
- CONDITION,值为-2,示意以后节点在期待condition,也就是在condition队列。
- PROPAGATE,值为-3,示意以后场景下后续的acquireShared可能得以执行。
参考的文章:《Java并发编程的艺术》
AbstractQueuedSynchronizer(AQS) 总结篇