J.U.C知识点梳理
java.util.concurrent包: 提供了并发编程的解决方案, J.U.C包里有两大核心:
- CAS(
compare and swap
)是java.util.concurrent.atomic包的基础. - AQS(
AbstractQueuedSynchronizer
)是java.util.concurrent.locks包以及一些常用类比如ReentrantLock
等类的基础.
J.U.C包的分类:
- 线程执行器executor,即一个任务执行和调度的框架,
- 锁locks(ReentrantLock和synchronized一样,都是排它锁)
- 原子变量类atomic,指一个操作是不会中断的,具有原子操作.
- 并发工具类tools
- 并发集合collections
并发工具类:
主要包括以下四个同步器,用于协助线程的同步:
- 闭锁CountDownLatch: 让主线程等待一组事件发生后继续执行.
其中,事件指的是CountDownLatch对象里的countDown()方法
.
当其他线程调用完countDown()方法后还是会继续执行的,即countDown()方法调用后不代表该子线程已经执行完毕
,而是告诉主线程,你可以继续执行,我这边已经开始了,不会拖你后腿. - 栅栏CyclicBarrier: 阻塞当前线程,等待其他线程
等待其他线程,且会阻塞自己当前线程,所有线程必须同时到达栅栏位置后才能继续执行.
所有线程到达栅栏处,可以出发执行另一个预先设置的线程.
- 信号量Semaphore: 控制某个资源可被同时访问的线程个数,Semaphore对象通过acquire()方法获取许可,使用结束后通过release()方法释放许可.
- 交换器Exchanger: 两个线程到达同步点后,相互交换数据,注意它只能用于两个线程之间.
BlockingQueue接口:
它提供了可阻塞的入队和出队操作.
如果队列满了,入队操作将被阻塞直到有空间可用.
如果队列空了,出队操作将会被阻塞直到有队列中有线程可用.
BlockingQueue中的方法:
从上到下依次为:
- add(): 表示向队尾插入元素,插入成功返回true, 插入失败报
IllegalStateException
异常. - offer(): 表示想队尾插入元素,插入成功返回true,插入失败返回false.
- put(): 表示向队尾插入元素,如果队列中没有足够空间就阻塞该线程,直到插入成功为止.
- offer(): 表示向队尾插入元素,如果没有足够空间,那就等待
timeout
时间,超时返回false,成功插入返回true. - take(): 表示移除队首元素并返回,如果没有就阻塞线程直到有有线程被移除为止.
- poll(): 表示移除队首元素并返回,如果没有就阻塞线程,同时等待
timeout
时间,如果时间到之前队列中有线程,那就直接移除并返回,否则返回null. - remainingCapacity(): 表示返回队列中剩余的容量.
- remove(Object o): 移除队列中的指定元素.
- contains(Object o): 判断是否队列中含有该元素,有就返回true.
- drainTo(): 移除所有队列中的元素到指定集合中,返回移除的元素个数.
- drainTo(Collection<? super E> c, int maxElements): 表示最多移除
maxElements
个元素到指定集合中.
BlockingQueue的作用:
主要用于生产者-消费者
模式,在多线程场景时生产者线程在队列尾部添加元素,而消费者线程则在队列头部消费元素,通过这种方式能够达到将任务的生产和消费进行隔离的目的.
BlockingQueue的实现类(都是线程安全的哈):
- ArrayBlockingQueue: 有边界的意思是它的
容量是有限的,我们必须在其初始化的时候指定其容量大小并且不能改变
,以先进先出的方式存储对象. - LinkedBlockingQueue: 它的阻塞队列大小的配置是可选的,如果我们初始化时指定大小那它就是有边界的,反之就是没有边界的(默认大小为Integer.MAX_VALUE),以先进先出的方式存储对象.
- PriorityBlockingQueue: 它是带优先级的,不是先进先出的,
按照优先级被移除
,同时它也是无界的,但是如果为空,那么取元素的操作就会被阻塞. - DelayQueue: 支持延时获取元素的无界队列,队列中的元素必须实现delay接口,在创建元素的时候可以指定多久才能从队列中获取元素.
- SynchronousQueue: 该队列只存储一个元素,当插入了一个元素后就会被阻塞直到元素被另一个线程消费掉.
- LinkedBlockingQueue: 它是2和5的合体,它是无锁操作.
- LinkedBlockingDeque: 就是一个双端队列啦,与线程的窃取工作相关联.