结论:
- start() 方法会启动一个新的线程,以及线程的一些准备工作(状态检查,加入通知线程组),然后 Java 虚拟机调用此线程的 run() 方法;
- run() 方法是直接执行 Runnable 对象的 run() 方法,是 main 线程下的一个普通线程,并不是多线程执行;
源码分析(Java8):
/**
* 使该线程开始执行;Java 虚拟机将调用此线程的 <code>run</code> 方法。
* 结果是两个线程同时运行:当前线程(从调用返回到<code>start</code>方法)和另一个线程(执行其<code>run</code>方法)。
* 多次启动一个线程永远是不合法的。特别是,线程一旦完成执行就可能不会被重新启动。
* @exception IllegalThreadStateException 如果线程已经启动,会抛出 java.lang.IllegalThreadStateException
* @see #run()
* @see #stop()
*/
public synchronized void start() {
/**
* VM 不会为 main() 方法线程或系统线程组 created/set 调用此方法。
* 将来添加到此方法的任何新功能可能也必须添加到 VM。
* "0" 状态值对应的线程状态为 "NEW"。
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/**
* 通知组该线程将要启动,以便可以将其添加到组的线程列表中,并且可以减少改组的未启动计数。
*/
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/**
* 什么也不做,如果 start0() 方法抛出 Throwable,则它将被向上传递到调用调用堆栈。
*/
}
}
}
private native void start0();
/**
* 如果此线程是使用单独的<code>Runnable</code>运行对象构造的,
* 则将调用该<code>Runnable</code>对象的<code>run</code>方法;否则,此方法不执行任何操作返回。
* <code>Thread</code>的子类应重写此方法。
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
start() 方法分析:
- 首先检查线程状态 threadStatus 是否为 0,0 状态代表线程的 “NEW” 状态,不为 0 会抛出 IllegalThreadStateException 异常;
- 将线程加入通知组;
- 然后调用一个 native 类型的 start0() 方法,此方法会在 VM 中调用此线程的 run() 方法,使线程进入 READY 状态;
run()方法分析:
- 检查 target(Runnable 对象)是否为空,不为空时直接调用 Runnable 的 run() 方法,只是main线程下一个普通线程,并不是多线程。