一文构建Java并发编程体系
一、概论
1.为什么要使用多线程
1、提高cpu利用率
2.多线程带来的问题
1、共享数据的线程安全性
2、多线程执行时的活跃性问题
3、多线程的所带来的性能损失问题
二、并发基础
1. 线程的创建
- 继承Thread类,重写run方法
- 实现Runable接口
new Thread(()->{
System.out.println(1);
}).start();
- 实现Callable接口: FutureTask实现了Runnable接口
FutureTask<Boolean> task = new FutureTask(()-> ture);
new Thread(task).start();
task.get();
2. 线程的6种状态
- 初始(NEW):
- 运行(RUNNABLE)
- 阻塞(BLOCKED)
- 等待(WAITING)
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回
- 终止(TERMINATED):表示该线程已经执行完毕
3. 操作线程的状态
4. 死锁
两辆车在窄路上阻塞;
5. 用户进程和守护进程
用户进程:
守护进程: 垃圾回收机制
6. ThreadLocal(需要吃透源码)
核心逻辑:set、get方法其中的核心就是
ThreadLocalMap getMap(Thread.currentThread());
7. 线程安全问题
8. 共享变量的内存可见性问题
9. synchronized关键字
使用:
- 同步代码块:括号中的对象
- 静态方法: Class对象
- 普通方法: 该实例对象
java对象在内存中:
synchronized: 在 java 虚拟机中,线程一旦进入到被synchronized修饰的方法或代码块时,指定的锁对象通过某些操作将对象头中的LockWord指向monitor 的起始地址与之关联,同时monitor 中的Owner存放拥有该锁的线程的唯一标识,确保一次只能有一个线程执行该部分的代码,线程在获取锁之前不允许执行该部分的代码。
10. volatile关键字
java内存模型
volatile
https://zhuanlan.zhihu.com/p/29881777
11. 原子性操作
12.CAS操作
13. Unsafe类
14. Java指令重排
15. 伪共享
16. 锁的概念
三、JUC并发包(java.utils.concurrent)
1.线程池
1)核心数据结构( workers+workQueue)
- 线程集合(workers):存放执行任务的线程,是一个HashSet;
- 任务等待队列(workQueue):存放等待线程池调度执行的任务,是一个阻塞式队列BlockingQueue
2) 构造函数
public ThreadPoolExecutor( int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize: 核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime: 存活时间
- TimeUnit: 时间单位
- BlockingQueue: 任务等待队列
- RejectedExecutionHandler 拒绝策略