一、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()方法还是在主线程中执行。并没有起到新启线程的目的。
二、start方法具体作用
那么运行start()方法,具体都做了什么呢?
- 通知JVM有空闲的时候启动新线程,等待线程调度器执行。不一定会马上执行,线程执行顺序也无法保证。
- start()方法会涉及到两个线程,主线程和子线程。子线程是需要先做一些准备工作才能运行的。比如,让自己处于就绪状态(获取到除了cpu以外的其他资源,比如设置了上下文,栈,线程状态,pc指向了程序运行的位置)。准备工作做完后,才会被JVM或者操作系统调度到运行状态,等待获取cpu资源,再到运行状态,运行run方法中的代码。可见,一个线程的执行,并不简单。
三、start方法的使用注意:
那么在调用start()方法时,应该注意些什么?
public class CantStartTwice {
public static void main(String[] args) {
Thread thread = new Thread();
thread.start();
thread.start();
}
}
比如不小心运行了两次start(),运行结果如下:
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at startthread.CantStartTwice.main(CantStartTwice.java:11)
出现了非法的线程状态异常。
其原因为,一旦开始执行就从最开始的new状态,到后续的状态,比如runnable状态。一旦线程执行完毕,就会变成终止状态,而终止状态永远不能返回回去,所以才会抛出这个异常。
四、start源码解析
在java.lang.Thread中,源码如下:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
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();
可知,start方法主要进行了如下逻辑:
1.启动新线程检查线程状态
2.加入线程组
3.调用start0()
网友评论