Thread 线程
>>>什么是进程?
程序:(编写的应用程序,未运行,属于静态的)
进程 :(运行的应用程序,CPU分配了资源,属于动态的)
线程:(进行的执行。包含多个线程,是一对多的关系,是处理程序的执行者)
Java中main线程是“主线程”,是程序执行的必要条件 ,JVM系统的入口
在main线程的原有数量之外增加的线程,与main线程并行并发的运行,称为“多线程”
>>>并发与并行的关系?
并发:多线程同时开启,但对数据资源的操作顺序不同(单核CPU),可能有序,也可能无序。
进程并发关系人类无法用肉眼识别,计算机运行速度纳米级别,产生同时执行的错觉
计算机一定是多线程,即使你不创建线程也会有多个线程,后台主线程,gc线程等
并行:多线程同时开启,对数据资源同一时刻操作(多核CPU)
// 查看CPU电脑核心数
Runtime runtim = Runtime.getRuntime();
int cpuNums = runtime.availableProcessors();
>>>多线程的现实应用:
- 现实生活中:电影播放时,线程图像&线程声音&线程字幕,多线程保证用户的体验。
- 程序执行中:Java程序运行时,JVM垃圾回收对堆中垃圾对象清理,保证内存利用。
所有的线程是由操作系统分配的,所以多线程跟操作系统关系密切。
操作系统为进程来分配足够的线程以保证运行,并且记录线程执行进程的进度。
>>>程序中多线程最大的好处?
- 保证吞吐量: 一个客户端的Request就需要一个线程执行任务,后面的请求需要排队等待才能被执行。使用多线程多,多个客户端的Request由多个线程去并发或并行执行。
- 伸缩性: 充分发挥CPU的多核性能
>>>多线程执行优先权
多线程优先执行权为5,最大修改值为10。但实际执行权由CPU分配资源决定。
一个进程开辟了多个线程,线程的执行权重由CPU调度器安排调度,人为不得干预
>>>守护线程&&用户线程
守护线程监视用户线程,当用户线程终止时,将影响到守护线程,会缓缓的进行终止。
而用户线程不受守护线程的影响。
JVM守护线程:垃圾回收机制
>>>死锁现象
A锁B资源(对象或类),A拿不到自己的资源无法执行
B锁A资源(对象或类),B拿不到自己的资源无法执行
以上两种情况同时发生即可出现死锁现象,都无法释放资源
>如何创建线程?
>>> ㈠ extends Thread:
public class Main {
public static void main(String[] args) {
// 创建线程:
UserThread userThread = new UserThread();
// 开启多线程: 通过start()方法执行线程体run()任务
userThread.start();
// 注意: 这种使用是main主线程来执行run()任务
userThread.run();
}
}
class UserThread extends Thread{
/**
* 重写父类Tread的run线程任务方法
*/
@Override
public void run() {
// 在方法体中我们可以定义线程的任务
System.out.println("此方法可以main线程执行,也可以其他线程执行");
super.run();
}
}
[缺点] 类中应该避免单继承出现,一个Tread类对应一个run()方法不共享
>>> ㈡ 实现Runable接口:
[优点] 避免单继承,将聚合关系变为依赖关系,多个Thread对象共享执行一份方法run()
>>> ㈢ 实现Callable接口:
[优点] 此方式必须有返回值
[缺点] 结构较为复复杂,并不是重写了run方法
>>> ㈣ 线程池方式:
- Executors类,一系列创建线程池的静态方法,以及多种拒绝策略
- ThreadPoolExecutor类,通过构造方法自定义线程池,以及多种线程工厂
[优点] 最佳推荐,自动化装配,节省资源,资源循环利用,利于管理
通过submit()提交线程任务,运行Callable或者Runable的实现类,线程执行是实现类的run方法。
>Thread类中方法
- setName设置线程别名
- getName获取线程别名
- start线程开始执行:调用底层start0()方法
- run执行线程对象简单的run方法
- setPriority设置优先级
- getPriority获取优先级
- sleep睡眠
- interrupt中断线程(不是中止结束,比如休眠被唤醒)
- yield线程尝试礼让,调用自己的(主要有CPU决定,线程资源越紧张概率越高)
我问业务员是否把资源让另一个紧急情况的人,由业务员决定,业务员资源充足,则都同时进行服务,业务员发现资源不充足,由你提出了将资源让给需要的人,这时业务员才会专注于帮助需要的人
- join线程插队,调用别人的(尝试让其他线程先执行任务,主动让其他线程插入前面完成任务,一定成功)
我和其他人排队到业务厅,但某事某刻我选择主动让其他人先插队到我的前面先完成业务
>Thread类中的设计者模式
- 静态代理
由于Thread方法实现了Runnable接口。
选择实现Runnable接口的方式创建线程,把Runable的实现对象丢进Thread构造方法,将会静态代理
,代理模式与适配器模式不同:适配器模式用于衔接,代理模式用于方法的增强,核心Proxy类用于扩展
>多线程安全问题
同一份资源,多线程资源抢夺问题 ,对资源进行操作,安全问题将会发生。
数值类型的值引用是罪魁祸首,线程拷贝数值遍历获得数值副本
JConsole监控:线程事件改多看得见摸得着