CAS(compare and swap):高效实现线程安全性的方法
- 支持原子更新操作,适用于计数器、序列发生器等场景
- 属于乐观锁机制,号称lock-free
- CAS操作失败时由开发者决定是继续尝试还是进行别的操作
缺点:
- 若循环时间长,则开销很大
- 只能保证一个共享变量的原子操作
- ABA问题(当一个变量被初次读取的时候是A,后面赋值的时候也是A,那么不能保证A没有被修改过)
- 解决ABA问题,可以使用AtomicStampedReference,控制变量的版本
JAVA线程池
利用Executors创建不同的线程池满足不同的场景(解决多线程并发但单个线程实际执行时间短的问题)
创建线程池的方法
Fork/Join框架
把大任务分割成若干个小任务并行执行,最终汇总每个小任务结果后得到大任务结果的框架
Work-Stealing算法:某个线程从其他队列里窃取任务来执行。上述框架分成多个小任务,有些任务完成的比较快,那么它可以从其他较慢的任务中获取任务,解决竞争的方法是使用双端队列。
为什么使用线程池
- 降低资源消耗
- 提供线程的可管理性
J.U.C的三个Executor接口
- Executor:运行新任务的简单接口,将任务提交和任务执行细节解耦
- ExecutorService:具备管理执行器和任务生命周期的方法,提交任务机制更完善
- ScheduledExecutorService:支持Future和定期执行任务
ThreadPoolExecutor的构造函数的参数
新任务提交execute执行后的判断:
如果运行的线程数小于CorePoolSize,则新建线程
如果大于CorePoolSize小于maximumPoolSize,则先放到workQueue,如果满了,操作创建新线程
如果大于maximumPoolSize,则先放到workQueue,如果满了则handler操作
线程池的状态
线程池的生命周期