JUC
2019-10-17 13:19:51 7 举报
AI智能生成
Java JUC
作者其他创作
大纲/内容
JUC
JUC原子类
AtomicLong是作用是对长整形进行原子操作。
AtomicLongArray的作用则是对\"长整形数组\"进行原子操作。
AtomicReference是作用是对\"对象\"进行原子操作。
AtomicLongFieldUpdater可以对指定\"类的 'volatile long'类型的成员\"进行原子更新。它是基于反射原理实现的
JUC锁
同步锁synchronized/互斥锁ReentrantLock
JUC包中的锁
接口:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件抽象类:AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizerReentrantLock独占锁,ReentrantReadWriteLock读写锁CountDownLatch,CyclicBarrier和Semaphore是通过AQS来实现
基本概念
AQS -- 指AbstractQueuedSynchronizer类
分为“独占锁”和“共享锁”两种
CLH队列是AQS中“等待锁”的线程队列
CAS函数 -- Compare And Swap
比较并交换函数,它是原子操作函数
AQS解析
共享
acquireShared(int)
doAcquireShared(int)
releaseShared()
doReleaseShared()
独占
2. acquire()
一. tryAcquire()
tryAcquire()尝试直接去获取资源,如果成功则直接返回;
二. addWaiter()
将当前线程加入到等待队列的队尾,并返回当前线程所在的结点
三. acquireQueued()
使线程在等待队列中获取资源,一直获取到资源后才返回。如果在整个等待过程中被中断过,则返回true,否则返回false
四. selfInterrupt()
让线程去休息,真正进入等待状态。
3.release(int)
tryRelease(int)
此方法是共享模式下线程释放共享资源的顶层入口,会释放指定量的资源,如果成功释放且允许唤醒等待线程,它会唤醒等待队列里的其他线程来获取资源
unparkSuccessor(Node)
Mutex(互斥锁)
Mutex是一个不可重入的互斥锁实现。锁资源(AQS里的state)只有两种状态:0表示未锁定,1表示锁定
Condition
能够更加精细的控制多线程的休眠与唤醒
LockSupport
LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题
ReadWriteLock
ReentrantReadWriteLock
CountDownLatch
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CountDownLatch是通过“共享锁”实现的。在创建CountDownLatch中时,会传递一个int类型参数count,该参数是“锁计数器”的初始状态,表示该“共享锁”最多能被count给线程同时获取。当某线程调用该CountDownLatch对象的await()方法时,该线程会等待“共享锁”可用时,才能获取“共享锁”进而继续运行。而“共享锁”可用的条件,就是“锁计数器”的值为0!而“锁计数器”的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时,才将“锁计数器”-1;通过这种方式,必须有count个线程调用countDown()之后,“锁计数器”才为0,而前面提到的等待线程才能继续运行!
CyclicBarrier
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)
Semaphore
Semaphore是一个计数信号量,它的本质是一个\"共享锁\"。
信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
JUC线程池
架构图
1. Executor
它是\"执行者\"接口,它是来执行任务的。,Executor提供了execute()接口来执行已提交的 Runnable 任务的对象。Executor存在的目的是提供一种将\"任务提交\"与\"任务如何运行\"分离开来的机制。
2. ExecutorService
ExecutorService继承于Executor。它是\"执行者服务\"接口,它是为\"执行者接口Executor\"服务而存在的;准确的话,ExecutorService提供了\"将任务提交给执行者的接口(submit方法)\",\
3.AbstractExecutorService
AbstractExecutorService是一个抽象类,它实现了ExecutorService接口。AbstractExecutorService存在的目的是为ExecutorService中的函数接口提供了默认实现。
4. ThreadPoolExecutor
继承于AbstractExecutorService抽象类
ScheduledThreadPoolExecutor
线程池状态
1. RUNNING
2. SHUTDOWN
3. STOP
4. TIDYING
5. TERMINATED
拒绝策略
AbortPolicy
当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常。
CallerRunsPolicy
当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
DiscardOldestPolicy
当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。
DiscardPolicy
当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。
(一) 创建“线程池”
1. newFixedThreadPool()
2. ThreadPoolExecutor()
ThreadFactory
程池中的ThreadFactory是一个线程工厂,线程池创建线程都是通过线程工厂对象(threadFactory)来完成的。
RejectedExecutionHandler
线程池默认会采用的是defaultHandler策略,即AbortPolicy策略。在AbortPolicy策略中,线程池拒绝任务时会抛出异常!
handler是ThreadPoolExecutor中拒绝策略的处理句柄。所谓拒绝策略,是指将任务添加到线程池中时,线程池拒绝该任务所采取的相应策略。
(二) 添加任务到“线程池”
1. execute()
execute()的作用是将任务添加到线程池中执行
2. addWorker()
3. submit()
submit()实际上也是通过调用execute()实现的
(三) 关闭“线程池”
shutdown()/shutdownNow()
ScheduledExecutorService
ScheduledExecutorService是一个接口,它继承于于ExecutorService。它相当于提供了\"延时\"和\"周期执行\"功能的ExecutorService。
ScheduledExecutorService提供了相应的函数接口,可以安排任务在给定的延迟后执行,也可以让任务周期的执行。
Callable 和 Future
Future用于表示异步计算的结果
Callable 是一个接口,它只包含一个call()方法。Callable是一个返回结果并且可能抛出异常的任务。
Executos
newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。
synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
newSingleThreadExecutor将corePoolSize和maximumPoolSize都设置为1,也使用的LinkedBlockingQueue;
LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize值是相等的,它使用的LinkedBlockingQueue;
LinkedBlockingQueue
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
JUC集合
Java集合包
2.Set的实现类主要有: HastSet和TreeSet。
(01) HashMap是存储“键-值对”的哈希表;它不是线程安全的,只适用于单线程。
(02) WeakHashMap是也是哈希表;和HashMap不同的是,HashMap的“键”是强引用类型,而WeakHashMap的“键”是弱引用类型,也就是说当WeakHashMap 中的某个键不再正常使用时,会被从WeakHashMap中被自动移除。WeakHashMap也不是线程安全的,只适用于单线程。
(03) Hashtable也是哈希表;和HashMap不同的是,Hashtable是线程安全的,支持并发。
(04) TreeMap也是哈希表,不过TreeMap中的“键-值对”是有序的,它是通过R-B Tree(红黑树)实现的;TreeMap不是线程安全的,只适用于单线程
JUC中的集合类
CopyOnWriteArrayList
1. CopyOnWriteArrayList的“动态数组”机制
它内部有个“volatile数组”(array)来保持数据。在“添加/修改/删除”数据时,都会新建一个数组,并将更新后的数据拷贝到新建的数组中,最后再将该数组赋值给“volatile数组”。
2. CopyOnWriteArrayList的“线程安全”机制
CopyOnWriteArrayList通过互斥锁来保护数据。在“添加/修改/删除”数据时,会先“获取互斥锁”,再修改完毕之后,先将数据更新到“volatile数组”中,然后再“释放互斥锁”;这样,就达到了保护数据的目的。
CopyOnWriteArraySet
CopyOnWriteArraySet是通过CopyOnWriteArrayList实现的,
ConcurrentHashMap
(01) ConcurrentHashMap继承于AbstractMap抽象类。
(02) Segment是ConcurrentHashMap中的内部类,它就是ConcurrentHashMap中的“锁分段”对应的存储结构。ConcurrentHashMap与Segment是组合关系,1个ConcurrentHashMap对象包含若干个Segment对象。在代码中,这表现为ConcurrentHashMap类中存在“Segment数组”成员。
(03) Segment类继承于ReentrantLock类,所以Segment本质上是一个可重入的互斥锁。
(04) HashEntry也是ConcurrentHashMap的内部类,是单向链表节点,存储着key-value键值对。Segment与HashEntry是组合关系,Segment类中存在“HashEntry数组”成员,“HashEntry数组”中的每个HashEntry就是一个单向链表
ConcurrentSkipListMap
跳表(Skip List),它是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的。
分支主题
ConcurrentSkipListSet
ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的
TreeSet是通过TreeMap实现的。
ArrayBlockingQueue
ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列。FIFO
是一个单向链表实现的阻塞队列。FIFO,默认容量大小等于Integer.MAX_VALUE。
LinkedBlockingDeque
LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式
ConcurrentLinkedQueue
是一个基于链接节点的无界线程安全队列,按照 FIFO,不可以放置null元素
0 条评论
回复 删除
下一页