在不同的地方学习了许多和并发相关的工具或者类并总结在了不同的博文中,这里做一个总的关系梳理并进行相关的补充,首先来看下 J.U.C 包下的分类:
主要分为如下几个部分:
- 线程执行器 executor 及其线程池实现类
- 锁 locks
- 原子变量类 atomic
- 并发工具类 tools
- 并发集合 collections
核心
- CAS:是java.util.concurrent.atomic包的基础
- AQS:是java.util.concurrent.locks包以及一些常用类比如Semophore,ReentrantLock等类的基础
原子操作类 atomic
Atomic包里一共提供了12个类,属于4种类型的原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新属性,Atomic包里的类基本都是使用Unsafe实现的包装类。
每种类型所具有的方法都差不多,这里列举一下各个类型的常用方法:
更新基本类型(AtomicInteger)
- int addAndGet(int data)
以原子的方式将输入的数值与实例中的值相加,返回结果 - boolean compareAndSet(int expect,int update)
如果输入的数值等于预期值,则以原子方式将该值设置为输入的值 - int getAndIncrement()
以原子方式加1 - int getAndSet(int newValue)
以原子方式设置为newValue的值,并返回旧值
更新数组类(AtomicIntegerArray)
- int addAndGet(int i,int data)
以原子方式将输入值与数组索引 i 的元素相加 - boolean compareAndSet(int i,int expect,int update)
如果当前值等于预期值,则以原子方式将数组i位置的元素设置成update值
并发集合 collections
CopyOnWrite
BlockingQueue
BlockingQueue主要用于生产者-消费者模式,在多线程场景时生产者线程在队列尾部添加元素,而消费者线程则在队列头部消费元素,这样可达到任务的生产和消费进行隔离的目的
根据底层实现的不同,我们可以划分出多个Blocking Queue的子类:
- ArrayBlockingQueue: 一个由数组结构组成的有界阻塞队列
有边界的必须在初始化时定义容量大小,以先进先出的方式去存储数据 - LinkedBlockingQueue: 一个由链表结构组成的有界/无界阻塞队列
它大小是可以指定的,也可以不指定,不指定就采用默认,也是先进先出 - PriorityBlockingQueue: 一个支持优先级排序的无界阻塞队列
优先级为主的,而不是先进先出,元素按照优先级顺序被移除 - DealyQueue:一个使用优先级队列实现的无界阻塞队列
是一个具有延迟取出的队列,当延迟期满,才能获取元素 - SynchronousQueue:一个不存储元素的阻塞队列
插入一个元素后就被堵塞,直到这个元素被其他进程消费掉 - LinkedTransferQueue:一个由链表结构组成的无界阻塞队列
是2,5的合体,性能比第2个更高,能存储更多的元素 - LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列
是一个双端队列,之前在Fork/Join那里讲过,是用的work-stealing算法实现的,每个消费者都有自己的双端队列,完成了就窃取其他消费者的队列末尾的任务
并发工具类 tools
闭锁 CountDownLatch、栅栏 CyclicBarrier、信号量 Semaphore 可以参考:J.U.C
交换器Exchanger
交换器主要用于线程之间进行数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。一个线程先到达同步点就会被阻塞,到另外一个线程也进入同步点为止,两个到达后就开始交换数据
线程执行器 Executor
参考:线程池原理