1.线程
1.1引入
在等待用户输入的时候,能不能生成随机数?
1.2作用
使程序可以同时执行多个事务
2.名词
进程
简介:一个正在进行的程序
从内存的角度来看,程序要运行时系统才会为其开辟一片运行内存,程序在运行完毕后系统将回收这片内存
线程
简介:一个代码的执行路径就是一个线程
多线程
简介:一个进程中有多个线程
注意:
多个线程在宏观上是同时进行的,在微观上是多个线程在不断抢夺cpu执行权,交替执行的
主线程
简介:一个进程自带一个线程,该线程被称为主线程
子线程
简介:一个进程除了主线程,其余都是子线程
同步
多个线程在执行时,必须先执行一个,在执行另外一个,不能同时操作同一个数据
异步
多个线程同时执行,互不干扰
3.线程与进程的关系
- 一个进程中可以有多个线程
- 一个进程至少要保证有一个前台线程存活,否则该进程也将被销毁
- 进程间数据不能共享,多个线程间数据可以共享
- 进程是一片运行内存,线程是一个执行路径
4.线程的组成
- 运行数据
- 栈,每个线程都有其各自的栈内存
- 堆,多个线程共享一个堆内存
2.CPU时间片
当线程抢夺到CPU执行权之后可执行的时间
3.线程的逻辑
5.线程的创建
方案1
方式1
- 创建一个类
- 该类继承于Thread类
- 重写run方法
- 创建该类对象
方式2
使用匿名内部类的形式创建线程对象
方案2
将线程任务(Runabble)与线程(Thread)分开
方式1
- 创建一个类实现Runabble接口
- 重写run方法
- 创建线程任务对象
- 创建线程对象,传入线程任务对象
方式2
思想:使用匿名内部类的形式创建线程任务对象
6.线程的方法
启动
语法:
线程对象.start();
注意:
使用线程对象调用start方法才会开启新的执行路径
如果使用线程对象调用run方法相当于对象调用方法,并没有开启新的执行路径
消亡
语法:
线程对象.stop();可以让线程停止,但是方法已经过时
线程对象.destory();让程序崩溃,方法已过时
线程在什么情况下消亡?
线程执行完run方法中代码就会等待系统回收
注意:
一般来说开启线程我们将不在管理线程,等线程中run方法执行完毕后会自动销毁
线程一经启动不受控制
获取当前线程
语法:
Thread 当前线程对象=Thread.currentThread();
注意:
在那个线程中使用该方法,就是获取哪个线程的对象
名称
设置名称
方法1
在创建对象时传入线程名称
方法2
在线程启动前通过setName设置线程名称
线程对象.setName(线程名称);
因为线程是有默认名称的,
获取名称
String 线程名称=线程对象.getName();
休眠
作用:线程等待一会
语法:
Thread.sleep(休眠时间);
注意:
- 休眠时间单位为毫秒
- 在哪个线程中就是让哪个线程休眠
- 不会释放锁对象
合并
作用:将多个线程合并为一个线程
语法:
线程对象.join();
注意:
在哪个线程中使用该方法就是将那个线程合并到当前线程中
礼让
作用:放弃本次抢夺到的CPU执行权,重新参与抢夺
语法:
Thread.yield();
注意:
在哪个线程中使用就是让哪个线程放弃本次CPU执行权
设置优先级
作用:增大或减小线程抢夺到CPU执行权的概率
语法:
设置优先级
线程对象.setPriority(优先级);
获取优先级
Int 线程优先级=线程对象.getPrioity();
注意:
- 优先级取值范围1~10,超过范围会报错
- 在线程启动前设置
- 线程的优先级是5.
守护线程
子线程分为两种:
前台线程
守护线程(后台线程)
如果创建一个子线程,默认是前台线程
可以通过
线程对象.setDaemon(true);将子线程设置为守护线程
前台线程与守护线程的区别
当一个进程有前台线程存活,那么该进程就不会被系统回收,直到当前进程中所有前台线程都执行完毕后,进程才会被系统回收
如果一个进程所有前台线程都执行完毕,还有守护线程正在执行,那么此时不管守护线程是否执行完毕,进程都将被销毁
7.线程的生命周期
初始状态:NEW
线程创建后,到启动前
就绪状态:Ready
线程启动后,但是没有抢夺到CPU执行权
运行状态:Running
线程抢夺到CPU执行权,正在执行run方法中的代码
当CPU执行权时间到了后
如果run方法中的代码执行完毕,进入终止状态
如果run方法中的代码没有执行完毕,会回到就绪状态
终止状态:Terminated
当线程执行完run方法中的代码后会进入该状态,等待系统回收
等待状态:Timed waiting
有限期等待
如使用线程调用sleep方法,线程会进入到有限期等待
无限期等待
如A线程合并B线程,B线程就会陷入无限期等待