JUC
创建线程
继承Tread类
继承实现,只能继承一个类,不能再继承其他类
run 方法
实现Runable
实现接口,可以再继承或实现
run 方法
创建实例,传入Tread ,再执行
实现Callable
可以返回数据
call 方法
返回数据放再FutureTesk
创建实例,传入Tread ,再执行
JMM java内存模型
这是一个规约,定义了程序各个变量的访问方式
同步的规定
- 线程解锁前,必须把共享变量的值刷新回主内存
- 线程加锁前,必须读取主内存的最新值到自己的工作内存
- 加锁解锁是同一把锁
具体的
- 内存可见性
- 保证原子性
- 有序性
volatile 关键字
作用:
- 内存可见性
- 不保证原子性
- 禁止重排
指令重排
源代码->编译器的优化重排->指令并行的重排->内存系统的重排->最终指令
volatile实现禁止指令重排实现
内存屏障(Memory Barrier) 又称内存栅栏,是一个CPU指令,它的作用有两个:
- 是保证特定操作的执行顺序
- 是保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)。
由于编译器和处理器都能执行指令重排优化。如果在指令间插入一条MemoryBarrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。内存屏障另外-一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。
原子变量
提供常用的原子变量
-
volatile 保证内存可见性
-
CAS 保证变量原子性
CAS 比较并交换
原理:unsafe 类通过cpu原语保证原子性 自旋锁
缺点:自旋锁失败一直尝试,cpu开销大
只能保证一个共享变量的原子操作
ABA
规避ABA问题,加时间戳
原子引用AtomicReference<>
带时间戳的原子引用AtomicStampedReference<>
同步集合
collections.synchronizedList();
collections.synchronizedSet();
collections.synchronizedMap();
CopyOnWirte 复制并写入
CopyOnWirteArrayList
CopyOnWirteArraySet
ConcurrentHashMap 锁分段机制
Hashtable 整体上锁
ConcurrentHashMap 分段上锁
HashMap 没有上锁
锁
公平锁/非公平锁
按照顺序 就是公平锁,按照线程优先级的 ,就是非公平锁
synchronization 也是非公平锁
lock 默认非公平锁
可以创建公平锁
非公平锁的优点是吞吐量比公平锁大
可重入锁(递归锁)
线程可以进入任何一个它已经拥有的锁所同步着的代码块。
synchronization/lock 都是可重入锁
自旋锁
CAS
独占锁/共享锁/互斥锁
ReadWriteLock 读写锁
readLock 读锁 共享锁
独占锁:writeLock 写锁 ,lock ,synchronization
显示锁/隐式锁
synchronization 隐式锁
lock 显示锁
乐观锁/悲观锁
synchronization悲观锁
lock 乐观锁
CountDownLatch 闭锁
需要完成某些必要的线程完成,才能运行当前线程 线程减法
使用Callable实现线程,对于类FutrueTask 可用于闭锁
CyclicBarrier
需要完成某些必要的线程完成,才能运行当前线程 线程加法
Semaphore
多线程抢夺共享资源
生产者与消费者
等待唤醒机制
synchronization 可能产生线程未被唤醒 将 else 取消
wait notify notifyAll
lock
condition 类
await signal signalAll
虚假唤醒问题
synchronization ,判断的地方使用循环 解决
线程交替
使用lock的线程通信实现
阻塞队列 BlockingQueue接口
ArrayBlockingQueue: 由数组结构组成的有界阻塞队列。
LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_ VALUE)阻 塞队列
PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
DelayQueue:使用优先级队列实现的延迟无界阻塞队列。
SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列。
LinkedTransferQueue:由链表结构组成的无界阻塞队列。
LinkedBlockingDeque:由链表结构组成的双向阻塞队列
方法类型 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
检查 | element() | peek() | 不可用 | 不可用 |
线程池
ThreadPoolExecutor
七大参数:
int corePoolsize:核心线程数
int maximumPoolSize 最大线程数
long keepAliveTime 多余线程存活时间
TimeUnit unit 时间单位
BlockingQueue workQueue 阻塞队列
ThreadFactory threadFactory 线程工厂
RejectedExecutionHandler handler 拒绝策略
线程数
cpu核数+1
cpu核数*2
拒绝策略
AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行。
CallerRunsPolicy: "调用者运行"一种调节机制, 该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。
工具类: Executors
ExecutorService newFixedThreadPool() :创建固定大小的线程池
ExecutorService newCachedThreadPool() :缓存线程池, 线程池的数量不固定,可以根据需求自动的更改数量。
ExecutorService newSingleThreadExecutor() :创建单个线程池。线程池中只有一个线程
ScheduledExecutorService newScheduledThreadPool() :创建固定大小的线程,可以延迟或定时的执行任务。
优势
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配, 调优和监控
死锁
多个线程争抢资源互相等待的现象
ForkJoinPool 分支合并框架
ForkJoinPool
RecursiveTask
RecursiveActio n