- 目录
- 一、多线程专题
- 1、线程与进程的区别
- 2、实现多线程的方式
- 3、线程的五种状态
- 4、线程死锁及解决办法
- 1)死锁条件
- 2)死锁解决
- 二、线程池专题
目录
一、多线程专题 1、线程与进程的区别
| 类型 | 根本区别 | 切换速度 |
|---|---|---|
| 线程 | 线程是处理器任务调度与执行的基本单位 | 同一类型线程共享数据空间与所在进程的资源,切换不涉及虚拟地址空间,且每个线程有独立的程序计数器与虚拟机栈,线程切换速度快; |
| 进程 | 进程是操作系统资源分配的基本单位 | 进程之间的地址空间与资源都是相互独立的,进程切换涉及到:切换页表以使用新的虚拟地址空间(进程切换后,页表缓存失效,导致了虚拟地址转换为物理地址很慢)、内核态与用户态的切换、硬件上下文的切换, |
2、实现多线程的方式
| 方式 | 描述 |
|---|---|
| 实现Runnable接口 / Callable接口 | ① 重写run()方法或者call()方法 ② Runnable接口无返回值,Callable接口有返回值 ③ call()可以抛出异常,run()不行 ④ Callable任务提供了Future对象(阻塞式等待),可以通过它获取异步执行结果 |
| 继承Thread类 | 缺点:不能继承其它类 |
| 线程池 | 4种线程池类型、5种阻塞队列、7大核心参数、4种拒绝策略 |
3、线程的五种状态
| 状态 | 时机 | 描述 |
|---|---|---|
| 新建 | Thread t = new MyThread() | 线程创建后的初始状态 |
| 就绪 | 调用start()方法时 | 进入就绪状态,等待被CPU调用后才执行,现在不执行 |
| 运行 | CPU调用就绪状态的线程时 | 只有就绪状态才能变成运行状态 |
| 阻塞 | 调用阻塞方法时 | ① 等待阻塞: 调用wait()方法时 ② 同步阻塞: 获取synchronized锁失败时 ③ 其它阻塞: 调用sleep() / join()方法时,或者发出I/O请求时;阻塞完会线程为重新变为就绪状态 |
| 死亡 | 线程执行结束或出现异常 | run() / call() 执行结束或run()异常退出,call()可以捕获异常 |
| 死锁条件 | 描述 | 破坏死锁条件 |
|---|---|---|
| 互斥 | 任一时刻资源只被一个线程获取 | 不能破坏,我们本来就想让临界资源互斥 |
| 请求与保持 | 一个进程因请求资源阻塞时,对已持有的资源保持不放 | 一次性申请全部的资源 |
| 不剥夺 | 线程在没有使用完资源前,不能被其它线程所剥夺,只能主动释放 | 当申请不到其它资源时,主动释放自己持有的资源 |
| 循环等待 | 互相等待对方释放资源,造成头尾相连 | 锁排序,指定获取锁的顺序;资源排序,按顺序获取资源 |
| 方法 | 关键 | 描述 |
|---|---|---|
| 死锁预防 | 破坏死锁条件 | ① 允许资源抢占: 当一个线程长时间申请不到其它资源时,主动释放自己所持有的资源; ② 一次性申请全部的资源 ③ 资源排序或者锁排序,按顺序申请资源 |
| 死锁避免 | 系统在进行资源分配之前,计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待; | 银行家算法: 保证循环等待条件不成立 |
| 死锁检测 | 通过dfs深度优先遍历,遍历资源分配图检测是否存在环 | ① 无环:没有死锁 ② 有环,但是涉及到的资源类有多个资源:不一定会死锁; ③ 有环,但是涉及到的资源类仅有一个资源:死锁; |
| 死锁解除 | 终止死锁进程 / 抢占死锁进程的资源 | 打破循环等待条件 |
| 鸵鸟策略 | 忽略死锁 | 例如Linux、Windows等处理死锁都不采取任何行动,保持高性能 |



