多线程
概念
-
程序(Program)
语言编写的指令集合,指一段静态的代码。
-
进程
动态的,一个正在运行的程序,及程序的一次执行过程,存在[生命周期]。可并发多个线程,每条线程执行不同任务
进程的三种状态
- 就绪态
- 运行态
- 阻塞态
-
线程
进程中的一个单一顺序的控制流,作为调度和执行的最小单位,每个线程都拥有独立的运行栈和程序计数器,切换的开销小,共享同一个进程中的结构(方法区、堆)
线程的六种状态
- New(新建)
- Runnable(可运行)
- Blocked(阻塞)
- Waiting(等待)
- Timed Waiting(超时等待)
- Terminated(终止)
-
单线程
单线程的也就是程序执行时,所跑的程序路径(处理的东西)是连续顺序下来的,必须前面的处理好,后面的才会执行到。
-
多线程
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务, 也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
-
并发
把任务在不同的时间点交给处理器进行处理。在同一时间点,任务并不会同时运行
-
并行
把每一个任务分配给每一个处理器独立完成。在同一时间点,任务一定是同时运行
线程实现的两种方式
- 继承Thread类 (实现了Runnable接口,重写run方法)
- 实现Runnable接口
线程执行流程图
1.继承Thread类
- 当在main线程中启动一个子线程,main线程不会阻塞
- 主线程与子线程会交替 (使用JConsole【操作:直接在控制台输入JConsole关键字即可启动~】可以展示线程的运行情况,证明main线程与子线程是在交替切换的)
线程的启动,run方法没有真正的启动线程,Start方法才是真正的启动了线程;
start()方法调用start0() 方法后,该线程并不一定立马执行,只是将线程变成了可运行状态,具体什么时候执行,取决于CPU,有CPU统一调度。
2.实现Runnable接口
-
采用了静态代理模式
-
启动方式
Dog dog = new Dog();
Thread t = new Thread (dog);
t.start();
线程的启动只能是调用start方法!!!!
Thread与Runnable的区别
- 继承Thread或者实现Runnable接口本质上没有区别,Thread类本身就实现 了Runnable接口
- 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用
对静态代理模式-代码演示
package JavaTest;
public class RunnableProxy {
public static void main(String[] args) {
Cat tiger = new Cat();
ThreadProxy threadProxy = new ThreadProxy(tiger);
threadProxy.run();
}
}
class ThreadProxy implements Runnable {
private Runnable target =null; // 属性,类型是Runnable类型
@Override
public void run() {
if(target != null) {
target.run(); // 动态绑定
}
}
public ThreadProxy(Runnable target) {
this.target = target;
}
public void start() {
start0();
}
public void start0() {
run();
}
}
线程终止
- 满足条件退出
- 在指定条件退出线程循环
线程的常用方法
- setName // 设置线程名
- getName // 获取线程名
- start // 执行线程,底层调用的是start0方法
- run // 调用线程对象run方法
- setPriority // 获取线程优先级
- getPriority // 设计线程优先级
- sleep // 休眠
- interrupt // 中断线程 ,中断线程的休眠状态
第二组方法
- yield:线程的礼让,让出cup的时间,让其他线程执行,但是礼让的时间不确定,所以不一定礼让成功。
- join: 线程的插队,插队的线程一单插队成功,则肯定先执行完插队的线程所有内容
用户线程与守护线程
用户线程:工作线程,当线程的任务执行完或者通过方式结束
守护线程:为工作线程服务,当所有用户线程结束,守护线程自动结束
常见:垃圾回收器
public class ThreadTest2 {
public static void main(String[] args) throws InterruptedException {
MyDeamonThread mdt = new MyDeamonThread();
// 将mdt设置为守护线程,当所有线程结束后,mdt也自动结束
// 如果没有设置,那么及时main线程执行完毕,mdt也不退出
mdt.setDaemon(true);
mdt.start();
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println("宝强在辛苦工作,不知道马蓉在~");
}
//
}
}
class MyDeamonThread extends Thread {
@Override
public void run() {
for (; ; ) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("马蓉和宋喆在谋划~");
}
}
}
线程的寿命周期
- New(新建)
- Runnable(可运行) (Ready:等待被调度,Running:运行中)
- Blocked(阻塞)
- Waiting(等待)
- Timed Waiting(超时等待)
- Terminated(终止)