线程是程序执行的一个路径,每一个线程都有自己的局部变量表、程序计数器(指向正在执行的指令指针)以及各自的生命周期,当启动一个Java虚拟机(JVM)时,从操作系统开始就会创建一个新的进程(JVM)进程,JVM进程中将会派生或者创建很多线程。
启动新的线程,只有调用了Thread的start方法,才派生了一个新的线程。
线程的生命周期:NEW、RUNNABLE、RUNNING、BLOCKED、TERMINATED五种状态
线程的NEW状态(新建):
当我们用关键字new创建一个Thread对象时,此时它并不处于执行状态,因为没有调用start方法启动该线程,那么线程的状态为NEW状态。NEW状态通过start方法进入RUNNABLE状态。
线程的RUNNABLE状态(就绪):
线程对象进入RUNNABLE状态必须调用start方法,那么此时才是真正地在JVM进程中创建了一个线程(等待CPU的调度)。
线程的RUNNING状态(运行):
在该状态中,线程的状态可以发生如下的状态转换
1.直接进入TERMINATED状态,比如调用JDK已经不推荐使用的stop方法或者判断某个逻辑标识
2.进入BLOCKED状态,比如调用了sleep,或者wait方法而加入了waitSet中
3.进入某个阻塞的IO操作,比如因网络数据的读写而进入了BLOCKED状态
4.获取某个锁资源,从而加入到该锁的阻塞队列中而进入了BLOCKED状态
5.由于CPU的调度器轮询使该线程放弃执行,进入RUNNABLE状态
6.线程主动调用yield方法,CPU放弃执行权,进入RUNNABLE状态
线程的BLOCKED状态(阻塞):
该状态中,线程的状态可以发生如下的状态转换
1.直接进入TERMINATED状态,比如调用JDK不推荐使用的stop方法或者意外死亡(JVM Crash)
2.线程阻塞的操作结束,比如读取了想要的数据字节进入到RUNNABLE状态
3.线程完成了指定时间的休眠,进入到了RUNNABLE状态
4.Wait中的线程被其他线程notify/notifyall唤醒,进入RUNNABLE状态
5.线程获取到了某个锁资源,进入RUNNABLE状态
6.线程在阻塞过程中被打断,比如其他线程调用了interrupt方法,进入RUNNABLE状态
线程的TERMINATED状态(终止):
TERMINATED状态是一个线程的最终状态,在该状态中线程将不会切换到其他任何状态,线程进入TERMINATED状态,意味着该线程的整个生命周期都结束了,下列情况将会使线程进入TERMINATED状态
1.线程运行正常结束,结束生命周期
2.线程运行出错意外结束
3.JVM Crash,导致所有的线程都结束
Thread 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 */
}
}
}
private native void start0();
start方法的源码足够简单,最核心的部分是start0()这个本地方法,也就是JNI方法
import java.util.concurrent.TimeUnit;
public class Test15 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 模拟一: 重复启动一个线程
*/
Thread thread = new Thread() {
public void run() {
try {
TimeUnit.SECONDS.sleep(10);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
thread.start();
try {
TimeUnit.SECONDS.sleep(2);//休眠主线程,确保Thread运行结束,结束生命周期
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread.start();
}
}
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at com.chisaki.Test.Test15.main(Test15.java:23)
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 模拟二:重新激活已经结束生命周期的线程
*/
Thread thread = new Thread() {
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
try {
// TimeUnit提供了可读性更好的线程暂停操作
//TimeUnit.SECONDS.sleep(2) 等同于 Thread.sleep(2000)
TimeUnit.SECONDS.sleep(2);//休眠主线程,确保Thread运行结束,结束生命周期
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread.start();
}
}
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at com.chisaki.Test.Test2.main(Test2.java:44)
结论:都抛出 java.lang.IllegalThreadStateException 异常,但是本质是不一样的,Thread.start()源码中可以看到
if (threadStatus != 0)
throw new IllegalThreadStateException();
A zero status value corresponds to state "NEW" :threadStatus=0等同于线程状态为:NEW,只有NEW状态下,线程才能执行start()方法,thread.getState()可以知道线程所处状态,State是一个枚举类型
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}