开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
学习MOOC视频记录的笔记
启动线程的正确和错误方式
1.start() 和 run() 的比较
public class StartAndRunMethod {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName());
};
// main
runnable.run();
// Thread-0
new Thread(runnable).start();
}
}
2.start()方法原理解读
调用 start() 方法的顺序并不能决定线程执行的顺序
start() 方法含义
-
启动新线程
- 调用
start方法实际上只是告诉JVM你合适的时候来启动新线程 【请求JVM来运行这个线程,线程究竟何时运行是由线程调度器去决定的】 - 会同时让两个线程运行,即
main主线程和子线程,new Thread().start()是由主线程执行的,执行完成之后才创建的子线程。
- 调用
-
准备工作
(新线程)让自己处于就绪状态,已经获取了除了CPU之外的其他资源,已经设置了栈,上下文状态,PC等,只等获取CPU资源就可以进入运行状态执行run方法中的代码。
-
不能重复执行
start方法
/**
* 不能两次调用start方法,否则会报错
*/
public class CantStartTwice {
public static void main(String[] args) {
Thread thread = new Thread();
thread.start();
thread.start();
}
}
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at threadcoreknowledge.startthread.CantStartTwice.main(CantStartTwice.java:12)
报错提示为非法的线程状态,表示一旦开始执行线程状态就从最开始的New状态进入到后续的状态,一旦线程执行完毕就进入终止状态,终止状态永远无法返回回去。
start()源码解析
- 启动新线程检查线程状态
- 加入线程组
- 调用
start0()
public synchronized void start() {
// 检查是不是刚初始化还没有启动的状态
if (threadStatus != 0)
throw new IllegalThreadStateException();
// 加入线程组
group.add(this);
boolean started = false;
try {
// native 方法,代码由C/C++实现的
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
// Java线程状态初始值为0,表示还未启动
private volatile int threadStatus = 0;
3.run() 方法原理解读
- 源码解析
- 两种情况
@Override
public void run() {
if (target != null) {
target.run();
}
}
4.彩蛋:Java 名字的由来
Oak和LyricCAFE BABEclass文件16进制文件头Beans
启动线程———常见面试题问题
- 一个线程两次调用
start()方法会出现什么情况?为什么?
- 会抛出异常
- 由于线程会检查
threadStatus如果不符合(已经执行了start()方法) - 引申线程状态问题
- 既然
start()方法会调用run()方法,为什么我们选择调用start方法,而不是直接调用run()方法呢?
因为调用 start() 方法才是真正意义上启动了一个线程,它会经历线程的各个生命周期,而直接调用 run() 方法它就是一个普通的方法而已,也不会用子线程调用。