进程与线程

进程与线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+ 进程
+ 加载指令、管理内存、管理io
+ 程序的一个实例
+ java中资源分配的最小单位
+ 线程
+ 一个指令流
+ 一个进程内多个线程
+ java中最小调度单位
+ 对比
+ 进程基本相互独立,线程存在于进程中
+ 进程通信复杂
+ 不同计算机进程通信,http协议等
+ 线程通信简单
+ 共享进程内的内存,数据
+ 线程上下文切换成本低

并行并发的概念

并发

并发

并行

并行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
并发: 同一时间段,多个任务都在执行 (单位时间内不一定同时执行)
并行: 单位时间内,多个任务同时执行
+ 并发
+ 同一时间线程轮流使用cpu
+ concurrent
+ 单核cpu下
+ 实际串行执行
+ cpu时间片轮流执行
+ 宏观上并行
+ 并行
+ 多核cpu下
+ 每个核同时调度运行线程
+ 并发和并行都有
+ 并发:同一时间应对多件事
+ 并行:同一时间动手做多件事

线程应用

1
2
3
4
5
6
7
8
9
10
11
12
+ 异步async
+ 不需要等待结果返回,继续运行
+ 特点
+ 线程不同
+ 避免阻塞主线程
+ 提高吞吐量
+ 提高效率
+ 分布式的远程调用一般都是异步调,节省总响应时间
+ 取决最长时间
+ 多核下
+ 任务拆分、并行执行
+ 非阻塞io和异步io优化

Java线程

创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ 创建和运行线程
+ 1、直接使用Thread
+ 2、使用Runnable配合Thread
+ 把线程和任务分
+ lambda简化
+ idea智能替换
+ 能简化的,idea会有灰色提示
+ 方法1、2
+ 走的都是run()方法
+ runnable与线程池等配合
+ 脱离任务和线程继承体系
+ 3、FutureTask配合Thread
+ 可以返回任务执行结果
+ return + get
+ 参数:泛型 + callable接口
+ get()
+ 阻塞等待结果返回

线程运行

1
2
3
4
5
6
+ 线程运行
+ 现象
+ 查看和杀死
+ windows
+ linux
+ jconsole

线程运行原理

栈帧图解

栈帧原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
+ 线程运行原理
+ 栈与栈帧
+ 栈帧Frame
+ 线程中方法的调用
+ 栈帧图解
+ 程序运行
+ 类加载
+ 启动主线程,栈内存
+ 执行main方法,分配栈帧内存
+ 局部变量表(args、变量)
+ 返回地址
+ 执行method1,分配栈帧内存
+ 执行method2,分配栈帧内存
+ 堆中创建对象
+ 执行完毕,释放栈帧内存
+ 多线程情况
+ 断点模式
+ 可以控制每个线程前进
+ 线程栈之间独立,独立的栈内存
+ 线程上下文切换
+ cpu转去执行另一个线程
+ 切换产生原因
+ cpu时间片用完
+ 垃圾回收
+ 更高优先级线程
+ 线程调用一些方法
+ 记录当前线程状态
+ 程序计数器
+ 栈帧信息、局部变量、返回地址等
+ 频繁上下文切换影响性能

常见方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
+ 线程常见方法
+ start()
+ 线程进入就绪状态
+ run()
+ 线程启动后调用
+ join()
+ 等待线程运行结束
+ 超时时间
...
+ start 和 run
+ 调用run()只是普通调用方法
+ 未创建线程
+ 而run真正的意义是当线程start进入就绪态后被调度获得时间片时执行run方法由就绪态进入运行态
+ 这里感觉t1.start()方法后加个t1.join()保证t1线程执行完才打印更合理些,而且状态是TERMINATED。而运行时状态应该在run()方法中打印
+ start不能多次调用
+ 变成runnable就不能调用start
+ sleep()与yield
+ sleep()
+ running状态变成TIMED_WAITING:阻塞
+ interrupt打断睡眠
+ 睡眠线程抛出异常执行catch
+ 睡眠结束未必立即执行,需要cpu使用权
+ 可读性
+ TimeUnit的sleep,附带时间单位
+ yield()
+ 从running变成runnable就绪
+ 让出cpu使用权,有机会立即获得时间片
+ 线程优先级
+ setPriority()
+ sleep应用
+ while(true)
+ 加上sleep
+ 避免空转占满cpu
+ join()
+ 线程.join()
+ 等待某线程运行结束
+ 同步应用
+ 同步:需要等待返回结果
+ 限时同步:参数
+ 最长等待时间
+ interrupt()
+ 打断阻塞线程:sleep、wait、join
+ 抛出Interrupted异常
+ 打断标记设为false
+ 打断正常
+ 打断标记为true
+ 程序不结束
+ 根据打断标记可以主动结束线程
1
2
3
4
5
+ 过时方法
+ 造成死锁
+ 守护线程
+ 当非守护线程都结束,守护线程强制结束
+ 垃圾回收线程

设计模式

interrupt实现

image-20220314230843538

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ 两阶段终止模式
+ 错误思路
+ stop()
+ 强制杀死,锁资源无法释放
+ interrupt实现
+ sleep中被打断
+ 抛出异常,执行catch语句,继续运行
+ 手动打断,设置打断标记为真
+ 这里为什么还能进入下一次循环?是因为catch这里会处理异常,而不是抛出异常,抛出异常才会导致线程终止!这里打印红色异常信息不会导致线程终止
+ 非sleep时被打断,设置打断标记未真
+ 结束循环
+ interrupt细节
+ interrupted()会清除打断标记
+ interrupt打断park线程
+ park暂停
+ 打断标记为false时暂停
+ interrupt可打断park线程

线程状态

线程状态

image-20220314230908950

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
+ 五种状态
+ 初始状态
+ 创建线程对象
+ 可运行状态
+ 线程已被创建,可调度执行
+ 运行状态
+ 获取cpu时间片
+ 阻塞状态
+ 调用阻塞API
+ 终止状态
+ 线程执行完毕
+ 六种状态:根据Thread.State
+ new
+ 创建对象
+ runnable
+ 包括可运行、运行、阻塞状态
+ terminated
+ 终止状态
+ java API层面的阻塞
+ blocked
+ 拿不到锁
+ waiting
+ join()
+ timed waiting
+ sleep()
+ 六种状态演示
+ sleep不会释放锁,只会释放cpu资源;wait既会释放CPU又会释放锁资源
+ 拿不到锁,blocked

小结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+ 小结
+ 线程创建
+ 3种
+ api
+ join
+ interrupt
+ 线程状态
+ 五种
+ 六种
+ 应用
+ 异步调用
+ 同步等待join
+ 异步编排
+ 原理
+ 运行流程
+ 栈、栈帧
+ 上下文切换
+ 程序计数器
+ 创建源码
+ 设计模式
+ 两阶段终止interrupt