1线程开启
我们先来看一下源码
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 */
}
}
}
复制代码
2源码解读
首先我们来看方法体public synchronized void start(),其中用了synchronize关键字修饰,代表此方法有锁,并且锁对象是当前调用的对象,并且避免多线程同时启动一个线程。
if (threadStatus != 0)
throw new IllegalThreadStateException();
复制代码
如果这个线程不是初始状态就直接抛出非法线程状态异常,什么情况下会出现这种情况呢,比如一个需要执行一段时间的线程在很短的时间内连续start()方法调用了两次就会抛出异常。
并且我们可以点击看到threadStatus这个变量的定义:private volatile int threadStatus = 0;是volatile关键字修饰的,说明这个变量具有可见性和禁止指令重排序,能及时发现这个变量被其他线程改变,所以这里使用volatile关键字是非常有必要的。
group.add(this);
复制代码
上一章中我们遇到的是g.addUnstarted()线程组调用未开始的线程使未开始线程数量+1。这次是添加进线程组里,并使线程组里的线程+1,未开始线程数量-1。
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 */
}
}
复制代码
这里started是一个标志状态,设置初始状态为false,然后进行本地方法start0()的调用,如果成功开启,则设置started状态为true。 完全执行完之前,线程处于 Ready,完成后,只要cpu分配执行权,我们的线程就进入了Running状态。
如果starte0()方法出现异常,则在线程组中调用threadStartFailed(this)方法,这个方法里有一个remove,就是把我们线程组中记录的这个线程删除,并线程数-1,未开始线程数量+1。
并且threadStartFailed里有synchronize代码块,防止并发修改问题,所以修改数量不会出现问题。
为什么catch里什么都没有写呢?
Start0 这个异常,会直接反馈给我们的调用线程。 如果这个线程是在main线程,那么就会走Main函数里边的 thread.start方法抛出异常,然后main函数抛出异常。如果catch中进行处理, 我们的 thread.start方法感知不到异常,导致程序的错误的继续执行。
3最后总结
线程对象在初始化完成之后,调用start()方法就可以启动这个线程。线程start()方法的含义是:当前线程(即parent线程)同步告知Java虚拟机,只要线程规划器空闲,应立即启动调用start()方法的线程。