JUC
请滑走,自用,无营养警告⚠
目录
2.CAS
从引出下面的问题
AtomicInteger->CAS ->调用UnSafe类中的CAS方法直接操作内存 ->自旋: CAS思想 -> ABA
atomicInteger.getAndIncrement(){return unsafe.getAndInt(this,valueoffset,1)
AtomicInteger的value是volatile修饰的
缺:循环时间长,开销大/只能保证一个共享变量的原子操作/ABA
ABA解决:1.AtomicStampedReference修改版本号,时间戳 2.LongAdder
3.ArrayList不安全
初始10 扩容1.5 add没加syn
Arrays.copyOf(elementData, netCapacity) int newCapacity = oldCapacity + (oldCapacity >> 1);
ConcurrentModificationException 并发修改的异常
解决1vector 加锁了,并发性小 2. Collections.synchronizedList(new ArrayList<>());
3.CopyOnWriteArrayList:写时复制,读写分离 add里面加可重入锁
HashSet线程不安全:CopyOnWriteArraySet
HashMap 1 使用Collections.synchronizedMap 2使用 ConcurrentHashMap
HashTable
- 底层数组+链表实现,key value都不能为null,线程安全,修改数据时锁住整个HashTable,效率低
- 初始size为11,扩容:newsize = olesize*2+1
- 计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length
ConcurrentHashMap
- 分段的数组+链表实现,线程安全
- 整个Map分为N个Segment (读操作不加锁)
- 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容
5.阻塞队列
BlockingQueue 阻塞队列 接口 什么时候阻塞(即挂起),唤醒不需要程序员控制细节
七个实现类
-
ArrayBlockQueue:数组有界阻塞队列 LinkedBlockingQueue:链表假有界
-
PriorityBlockQueue:支持优先级排序的*
-
DelayQueue:使用优先级队列实现的延迟*阻塞队列
-
SynchronousQueue:生产一个,消费一个,不存储元素,不消费不生产
-
LinkedTransferQueue:*阻塞队列LinkedBlockingDeque:双向阻塞队列
【核心方法】
1 | 抛出异常:::队列满时add , 队列空时remove,抛异常 |
2 | 特殊值:::offer,成功true,失败false poll():成功返回出队列元素,队列没有就返回空 |
3 | 一直阻塞:::队列满,put 阻塞生产线直到可以put, 队列空时,take同理 |
4 | 超时退出:::队列满时,阻塞生产者线程一定时间 offer(e,time,unit) poll(time,unit) |
6.Synchronized和Lock的区别
synchronized属于JVM层面,ReentrantLock 是 JDK (juc)实现的。
monitorenter 只能在同步块 或 方法中 才能调用 wait/ notify
synchronized:不需要用户去手动释放锁,不用担心死锁
synchronized不可中断 ReentrantLock:可设置超时方法, 也可lockInterrupible()
非公平
ReentrantLock:精确唤醒
7.线程池 ThreadPoolExecutor
提交任务请求
-
正在运行线程小于corePoolSize,马上创建线程运行任务,大于或等于corePoolSize,任务放入队列
-
队列满了,创建非核心线程
-
大于maximumPoolSize,拒绝策略
-
当一个线程完成任务时,从队列中取下一个
-
当一个线程无事可做操作一定的时间,停掉线程,直到收缩到corePoolSize的大小
线程池7大参数
-
corePoolSize:核心线程数,线程池中的常驻核心线程数
-
有请求任务来之后,就会安排池中的线程去执行请求任务,达到corePoolSize后,放到缓存队列中
-
-
maximumPoolSize:线程池能够容纳同时执行的最大线程数
-
keepAliveTime:多余的空闲线程存活时间
-
unit:时间单位
-
workQueue:任务队列,被提交的但未被执行的任务
-
threadFactory:
-
handler:大于最大线程数
拒绝策略
-
AbortPolicy:抛异常
-
DiscardPolicy:直接丢弃任务,不予处理不抛异常
-
CallerRunsPolicy:不抛弃任务,不抛异常,而是将任务回退到调用者
-
DiscardOldestPolicy:抛弃队列中等待最久的任务,加入当前的
-
线程池创建的方法有:固定数的,单一的,可变的,那么在实际开发中,应该使用哪个?
都不用 运行的请求队列长度为:Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM
ExecutorService executorService = new ThreadPoolExecutor(参数)
executorService.execute(() -> {}) //for循环里
如何配置 corePoolSize 和 maximumPoolSize
-
CPU密集型 任务需要大量的运算,而没有阻塞,CPU一直全速运行,CPU核数 + 1个线程数
-
IO密集型,线程不一直在执行任务,则可能多的线程,CPU核数 / (1 - 阻塞系数) 阻塞系数在0.8 ~ 0.9左右
本文地址:https://blog.csdn.net/afeiererer/article/details/107631355