1.进程与线程
一个进程包含多个线程,线程之间共享进程的资源,进程去找操作系统(OS)去申请内存,进程把申请到的内存分派给线程来使用
线程是cpu调度的最小单位
CPU核心数和线程数的关系:1:2,四核对应8个逻辑处理器,意味着可以同时跑8个线程,但是为什么我们的pc没有运行八个逻辑处理器(线程)就卡死呢,就是因为CPU的时间片轮转机制
CPU时间片轮转机制
2.并行与并发
并行
并发:并发的概念一定要有时间单位,时间单位内执行了多少任务
多线程的好处:充分利用CPU资源,加快响应用户所用的时间,可以使我们的代码模块化、异步化、简单化
注意:
1.必须考虑线程的安全性,
2.死锁:死锁产生的条件
- 互斥条件:一个资源每次只能被一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
3.资源以及锁的竞争会导致性能下降
4.线程不可能无穷无尽:OS限制:Linux下最多1000个,windows:2000,新线程:os会给他分派资源,分派栈空间1M。单纯new1000个线程 ,就要1G左右,还有文件描述符(句柄、指针、引用的指向),会消耗大量的资源
3.多线程的启动方式
Java中的程序天生就是多线程的,启动线程的方式:
类:Thread:对线程的抽象
接口:Runnable:对任务的抽象
结束:
stop()
interrupt():对线程进行中断,(并不是终止:强制性的),而是添加了一个中断标志位(用isInterruptd()来判断),打了个招呼,说你应该中断了,可以不用理会,不是强制性的。所以线程是协作式的不是抢占式的,而且在kotlin中直接将多线程的处理叫做协程(Coroutines )
isInterrupted():boolean:当前线程是否被中断
static方法interrupted():判定完之后会将中断标志位置为false
4.使用方法
Thread里面直接调用
Runnable里:
public static class BarryLRunnable implements Runnable {
@Override
public void run() {
//先获取当前正在执行的线程然后再调佣isInterrupted()
while (!Thread.currentThread().isInterrupted()) {
//TODO
}
}
}
public static void main(String[] args) throws InterruptedException{
BarryLRunnable barryLRunnable = new BarryLRunnable();
Runnable target;
Thread barryThread = new Thread(barryLRunnable);
barryThread.start();
Thread.sleep(1000);
barryThread.interrupt();//添加中断标志位
}
应当注意的是当TODO部分有另外的线程要执行而中断当前线程时,捕获到异常之后会将标志位flag置为false
public static class BarryLRunnable implements Runnable {
@Override
public void run() {
//先获取当前正在执行的线程然后再调佣isInterrupted()
while (!Thread.currentThread().isInterrupted()) {
//TODO
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//捕捉到异常之后会将interrupt标志位置为false,所以我们需要手动调用interrupt中断方法
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
}
5.run()和start()的区别
xxx.run()永远执行在主线程,xxx.start()才会执行xxx线程
yield():将线程从运行转到可运行状态,时间片到期,只会让出时间片,不会让出锁
join():获取执行权进入运行状态,将线程串行,需要排队,join进去的线程先执行,优先级高
优先级0-10,默认为5
守护线程setDeamon(true),守护线程随着所有用户线程主的结束而结束,守护线程中finally不一定起作用
6.同步锁、内置锁
//用在同步块上
public void incCount() {
synchronized (obj) {
count++;
}
}
//用在方法上
public synchronized void incCount2() {
count++;
}
对象锁、类锁
volatile