1、启动线程的正确和错误方式
结论:使用start方法启动线程
1.1 start()和run()的比较
/**
* start方法和run方法
*/
public class StartAndRunMethod {
public static void main (String[] args) {
Runnable runnable = ()->{
System.out.println(Thread.currentThread().getName());
};
runnable.run();
new Thread(runnable).start();
}
}
输出:
main
Thread-0
是不是和我们想的不太一样
不建议使用直接调用的方式执行run方法,这样违背了我们创建线程的初衷。
1.2start方法的解读
1.2.1 start方法含义
-
启动新线程(通知JVM在空闲的情况下,启动新线程)
- 调用start方法的顺序并不能决定最后线程的执行顺序(执行顺序是要看JVM的状态和各种其他的因素)
- 会让两个线程同时运行。我们需要一个线程来执行start语句(通常是main线程),另一个线程就是start语句创建的新线程
-
新的线程要进行一系列的准备工作才能工作。
- 首先是自己处于就绪状态(自己已经获取到了除CPU以外的其他资源)
- 做完上叙工作之后,我们线程才能被JVM或OS调度到执行状态,调度到执行状态之后我们才能获得到CPU资源
- 然后才能调度到执行状态,执行方法内容
-
不可以重复调用start方法
Thread thread = new Thread(); thread.start(); thread.start();
此时抛出异常:IllegalThreadStateException非法的线程状态
- 一旦start,线程就会变化各种状态,一旦线程执行完毕,就会进入终止状态(该状态永远不可以变化了)所以我们再一次的start就会报错(可以结合后面的源码学习)
1.3 start源码解析
- 启动新线程检查线程状态
- 加入线程组
- 调用start0()
public synchronized void start() {
/* 判断状态是否正确 */
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* 加入线程组*/
group.add(this);
boolean started = false;
try {
start0();//调用start0方法
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private native void start0();
关于native方法(该方法不是使用Java写的,而是使用C++写的)主要是调用OS的方法
1.4 常见面试题
一个线程两次调用start方法会出现什么情况?why
分析start源码,在最开始的时候就会进行状态的判断,如果前面已经执行了start方法,就会报错(非法的线程状态)
在面试的时候要提到线程的状态,最开始是什么状态,然后是什么状态(不要问什么就答什么,一定要给知识点引申一下,往自己知道的知识点引)
既然start方法会调用run方法,为什么我们选择调用start方法,而不是直接调用run方法
只有使用了start方法,才是创建一个新线程。否则就是使用旧线程来执行run方法(比如说是main线程)
慕课网悟空老师课程笔记 https://coding.imooc.com/class/362.html
谢谢大家看到这里,如有不对的地方请在评论区指正