线程的介绍
线程是程序执行的一个路径,每一个线程都有自己的局部变量表、程序计数器(指向正在执行的指令指针)以及各自的生命周期,当启动了一个java虚拟机(JVM)时,从操作系统开始就会创建一个新的进程(JVM)进程,JWM进程中将会派生或者创建很多线程。
线程的生命周期
- NEW
- RUNNABLE
- RUNNING
- BLOCKEDD
- TERMINATED
当我们用new关键字创建Thread对象,并且还没调用start()方法,此时线程为NEW状态。
NEW状态的线程通过调用start()方法进入RUNNABLE,此时才是真正的在JVM进程中创建一个线程,线程一经启动并不会立即得到执行,还得听令于CPU的调度。我们把这样一个中间状态称为RUNNABLE。即使是在线程的执行逻辑中调用wait、sleep或者其他block的IO操作等,也必须获得COU的调度权,严格来讲,RUNNABLE的线程只能进入RINNOING状态或者意外终止。
一个正在RUNNING状态的线程事实上也是RUNNABLE的,但反过来不成立。
RUNNING状态可发生以下转换:
直接进入TERMINSTED,比如调用stop()方法或者判断某个逻辑标识。
进入BLOCKED状态,调用sleep()或者wait()方法而进入waitSet中。
进行某个阻塞的IO操作,比如因网络的数据读写而进入BLOCKED状态。
获取某个锁资源,从而加入到该锁的阻塞队列中而进入了BLOCKED状态。
由于CPU调度器轮询使该线程放弃执行,进入RANNABLE状态。
线程主动调用yeild()方法,放弃CPU执行权,进入RANNABLE状态。
BLOCKED状态可以发生以下转换:
直接进入TERMINATED,比如调用stop()方法或者JVM Crash。
线程阻塞操作结束,进入到RANNABLE状态。
线程完成了指定的休眠时间,进入到RUNNABLE状态。
Wait中的线程被其他线程notify/notifyall唤醒,进入到RUNNABLE状态。
线程在阻塞过程中被打断,比如调用了interrup方法,进入RUNNABLE状态。
进入TERMINATED状态:
该状态不会切换到别的任何状态。
线程运行正确结束,结束生命周期。
线程运行出错,意外结束。>JVM Crash导致所有线程都结束。
线程start方法剖析
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 */
}
}
}
在开始执行线程时,JVM会调用该线程的run方法,也就是说run方法是被JNI(本地方法)start0调用的。
不能两次启动Thread,否则就会抛出异常。
线程一经启动就会加入到ThreadGroup中。
线程生命结束,再次调用start方法是不允许的。