目录
一、线程的所有状态
二、状态转换
三、多线程初体验
一、线程的所有状态
状态是针对当前线程调度情况所描述的,又因为线程是调度的基本单位,所以我们所谈到的状态都是线程的属性。在java里对线程的状态,进行了一个更细的划分。
我们可以发现: 线程的状态是一个枚举类型 Thread.State
我们可以遍历一下线程状态枚举
状态 | 意义 |
NEW | 创建了Thread对象,但是还没有调用start(操作系统内核还没有创建PCB) |
TERMINATED | 操作系统内核的PCB已经执行完了,但Thread对象还存在 |
RUNNABLE | 可运行的,可分为:正在工作 和 即将开始工作 |
WATING | 表示不同原因的阻塞(表示线程PCB处在阻塞队列) |
TIME_WAITING | 表示不同原因的阻塞(表示线程PCB处在阻塞队列) |
BLOCKED | 表示不同原因的阻塞(表示线程PCB处在阻塞队列) |
二、状态转换
NEW状态: 线程对象创建完成,没有start()的状态。
TERMINATED状态: run()执行结束的状态。
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {for (int i = 0; i < 1000; i++) {}});System.out.println("start之前的状态: "+t.getState());t.start();t.join();System.out.println("run之后的状态: "+t.getState());}
TERMINATED状态实际是没什么意义的,因为一旦内核里的线程PCB销毁了,代码里的Thread对象t也没什么实际意义了,只是为了把t对象标识为" 无效状态 ",因为一个线程,只能start一次
RUNNABLE状态: 可运行的,可分为两种: 1. 在就绪队列里,随时可去CPU执行 2. 正在CPU执行
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {for (int i = 0; i < 1000; i++) {}});System.out.println("start之前的状态: "+t.getState());t.start();System.out.println("t正在运行的状态: "+t.getState());t.join();System.out.println("run之后的状态: "+t.getState());}
我们可以发现RUNNABLE状态,我们之所以可以看到这个状态,因为我们的线程没有写sleep,join等方法
三、多线程初体验
学习了这么多线程的知识,相信很多同学会问,多线程的意义到底是什么呢?
这里我们来看一段代码,单线程和多线程之间的差距。
场景: 我们需要给两个变量,各自自增100000w次。
public static void main(String[] args) {single();}public static void single() {long start = System.currentTimeMillis();int a = 0;for (int i = 0; i < 10_0000_0000L; i++) {a++;}int b = 0;for (int i = 0; i < 10_0000_0000L; i++) {b++;}long end = System.currentTimeMillis();System.out.println("单线程执行时间为: "+(end - start));}
多线程:
public static void main(String[] args) {multith();}public static void multith() {Thread t1 = new Thread(() ->{for (int i = 0; i < 10_0000_0000L; i++) {int a = 0;a++;}});Thread t2 = new Thread(() ->{for (int i = 0; i < 10_0000_0000L; i++) {int b = 0;b++;}});long start = System.currentTimeMillis();t1.start();t2.start();long end = System.currentTimeMillis();System.out.println("多线程执行时间为: "+(end - start));}
我们只是启动了t1,t2线程,并没有等到t1,t2执行结束(好比运动会裁判在运动员刚起跑就停止秒表是类似的,我们要想记录真正的时间,就得等运动员冲线)线程执行结束才可以。
public static void multith() {Thread t1 = new Thread(() ->{for (int i = 0; i < 10_0000_0000L; i++) {int a = 0;a++;}});Thread t2 = new Thread(() ->{for (int i = 0; i < 10_0000_0000L; i++) {int b = 0;b++;}});long start = System.currentTimeMillis();t1.start();t2.start();try {t1.join();t2.join();} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("多线程执行时间为: "+(end - start));}
我们这里的join的作用是让t1,t2线程执行结束,再去执行main函数。