线程
1、概念
1、进程:计算机上应用拆分成多个小任务(操作系统可以分配的最小单位)
2、线程:进程可以拆分成多个小任务(CPU可以处理的最小单位)
3、在某个时刻CPU的某个核中只能执行一个进程,这个进程中只能执行一个线程,** CPU只能执行一个线程,CPU可以轮换线程。**(轮换速度极快)
2、多线程的好处
线程的工作职责要么和CPU进行交互要么和硬件进行交互,当线程和硬件进行交互时CPU处于空闲状态,利用率较低。引入多线程可以去提高CPU的利用率(理论上可以达到100%)
3、实现多线程的方式
1.继承Thread类,重写run方法来描述线程任务信息,创建对象调用父类Thread类里start方法来开启线程。
1)定义一个类描述线程的任务信息
class TDemo extends Thread{}
2)在类里重写run方法
public void run() {}
3)在主方法里创建线程对象,创建描述线程任务信息类的对象
TDemo t=new TDemo();
3)调用父类的方法来开启线程
线程对象不能回头执行
t.start();
2.实现Runnable接口,重写run方法来描述线程任务信息,由Runanble接口实现类的对象来构建Thread类对象,调用start方法来开启线程(常用)
1)定义类去描述线程的任务信息
class RDemo implements Runnable{}
2)在类里重写run方法指定线程的任务信息
public void run() {}
3)创建描述线程信息类的对象
RDemo r=new RDemo();
Runnable接口的实现类对象
4)创建线程对象—Thread对象
Thread t=new Thread®;
5)调用start方法来开启线程
t.start();
4、多线程并发安全问题
线程之间存在相互抢占CPU执行权(随机),发生在代码的每一步,导致程序出现错乱数据(重复、跳过、负数等等)
5、多线程并发安全问题的解决方案(加锁)
5.1 同步代码块锁
synchronized(锁对象){线程核心内容}
根据锁对象来共享线程对象,被共享进来的线程对象可以保证执行代码块里的线程核心内容时每次只能出现一个线程对象,就可以避免线程核心内容出现线程抢占的问题。
1)可以把当前参与的线程对象共享进来的对象
2)方法区资源(可以共享所有的线程对象)
3)this(前提是参与的线程对象共享同一个Runnable实现类对象)
eg:
步骤(售票系统):
首先
创建描述卖票线程的任务信息
创建定义代表票的类
1)main方法
创建票类对象
设置剩余票数
创建多个售票人员(一个售票系统)
创建多个线程对象(给线程对象指定名称)
开启线程
2)描述线程任务信息的类
声明代表票类的对象
有参构造(保证创建的所有的Seller类的对象共享同一个Ticket类的对象—总票数一致)
重写Run方法—指定卖票过程
{
①循环执行
②使用同步代码块锁包住线程的核心内容,()填写锁对象—可以把线程对象共享进来的对象
}
5.2同步方法锁
在run方法上加上synchronized关键字来修饰方法,但会默认提供锁对象来共享线程对象,共享进来的线程对象在执行方法内容时可以保证只能每次有一个线程对象来执行
如果修饰的是非静态方法默认的锁对象是this
如果修饰的是静态方法法默认的锁对象是当前类.class(方法区资源可以共享所有线程对象)
6、同步和异步
1)同步:在某个时刻只能一个线程对象来访问资源(没有抢占)
2)异步:在某个时刻多个线程之间可以相互抢占资源(有抢占)
总:同步一定安全,不安全的一定是异步
7、死锁
是由锁的嵌套来产生的,通过死锁检测来让其中一个线程对象先执行,资源就可以释放,就解决了死锁问题。
8、等待唤醒机制(结合锁来使用)
通过wait方法、notify方法、notifyAll方法以及标志位来控制线程对象执行轨迹
eg:生产消费模型
9、sleep方法和wait方法
1)sleep方法可以指定休眠的时间到点自然醒,在休眠时间sleep方法来释放线程对象的CPU执行权,定义在Thread类里静态方法。
2)wait方法可以指定等待时间也可以不指定,如果指定等待时间也是到点自然醒如果没有指定等待时间就是需要手动唤醒,在等待期间释放线程对象的CPU执行权以及释放锁对象(可以抢占),定义在Object类里(可以保证被锁对象来调用)
10、线程的状态
新建—>就绪—>执行—>销毁
新建—>阻塞
就绪—>阻塞
执行—>阻塞
执行—>就绪
阻塞—>就绪
11、优先级
当作权重来尽量避免死锁的发生
优先级1-10,优先级越大的线程对象理论上抢占到资源的概率越大
如果优先级差值大于5理论上抢占到的概率会大一些
12、守护线程
如果被守护线程结束,随之守护线程也结束
如果不是手动设置成的守护线程就是被守护线程
被守护线程可以有多个,每个被守护线程结束、所有的守护线程才结束
内存里有最大的守护线程—GC