当Thread对象创建完成时,线程的生命周期便开始了。当线程任务中代码正常执行完毕或者线程抛出一个未捕获的异常或者错误时,线程的生命周期便会结束。
Java中线程的状态可以分为6个状态,分别是NEW(新建状态)、RUNNABLE(可运行状态)、BLOCKED(阻塞状态)、WAITING(等待状态)、TIMEDWAITING(定时等待状态)、TERMINATED(终止状态)。
1.NEW(新建状态)
创建一个线程对象后,该线程对象就处于新建状态,此时它不能运行,和其它Java对象一样,仅仅由JVM为其分配了内存,没有表现出任何线程的动态特征。
2.RUNNABLE(可运行状态)
当新建状态下的线程对象调用了start()方法,此时就会从新建状态进入可运行状态。在RUNNABLE状态内部又可细分为两种状态:READY(就绪状态)和RUNNING(运行状态),并且线程可以在这两个状态之间相互转换。
就绪状态:线程对象调用start()方法之后,等待JVM的调度,此时线程并没有运行;
运行状态:线程对象获得JVM调度,如果存在多个CPU,那么允许多个线程并行运行。
3.BLOCKED(阻塞状态)
处于运行状态的线程可能会由于某些原因失去CPU的执行权,暂时停止运行进入阻塞状态。此时JVM不会给线程分配CPU,直到线程重新进入就绪状态,才有机会转换到运行状态。阻塞状态的线程只能先进入就绪状态,不能直接进入运行状态。
线程一般会在以下两种情况下进入阻塞状态:
1>当线程A运行过程中,试图获取同步锁时,却被线程B获取,此时JVM把当前线程A存到对象的锁池中,线程A就会进入阻塞状态;
2>当线程运行过程中,发出I/O请求时,此时线程也会进入阻塞状态。
4.WAITING(等待状态)
当处于运行状态的线程调用了无时间参数限制的方法后,如wait()、join()等方法,就会将当前运行中的线程转换为等待状态。
处于等待状态中的线程不能立即争夺CPU使用权,必须等待其它线程执行特定的操作后,才有机会再次争夺CPU使用权,将等待状态的线程转换为运行状态。例如,调用wait()方法而处于等待状态中的线程,必须等待其它线程调用notify()或者notifyAll()方法唤醒当前等待中的线程;调用join()方法而处于等待状态中的线程,必须等待其它加入的线程终止。
5.TIMEDWAITING(定时等待状态)
当运行状态中的线程转换为定时等待状态中的线程与转换为等待状态中的线程操作类似,只是运行线程调用了有时间参数限制的方法,如sleep(long millis)、wait(long timeout)、join(long millis)等方法。
处于定时等待状态中的线程也不能立即争夺CPU的使用权,必须等待其它相关线程执行完特定的操作或者限时结束后,才有机会再次争夺CPU的使用权,将定时等待状态的线程转换为运行状态。例如,调用了wait(long timeout)方法而处于等待状态中的线程,需要通过其它线程调用notify()或者notifyAll()方法唤醒当前等待中的线程,或者等待限时结束后也可以进行状态转换。
6.TERMINATED(终止状态)
线程中的run()方法、call()方法正常执行完毕或者线程抛出一个未捕获的异常、错误,线程就进入终止状态。一旦进入终止状态,线程将不再拥有运行的资格,也不能转换到其它状态,生命周期结束。
public class ThreadState {
public static void main(String[] args) {
for (Thread.State state : Thread.State.values()) {
System.out.println(state);
}
}
}
运行结果:
线程状态转换图:
例1:验证NEW、RUNNABLE和TERMINATED
import java.util.SortedMap;
class MyThread extends Thread{
public MyThread(){
System.out.println("构造方法中的状态: Thread.currentThread().getState()="+Thread.currentThread().getState());
System.out.println("构造方法中的状态:this.getState()="+this.getState());
}
@Override
public void run(){
System.out.println("run方法中的状态:"+Thread.currentThread().getState());
}
}
public class Run1 {
public static void main(String[] args) {
try {
MyThread mythread=new MyThread();
System.out.println("main方法中的状态1:"+mythread.getState());
Thread.sleep(1000);
mythread.start();
Thread.sleep(1000);
System.out.println("main方法中的状态2:"+mythread.getState());
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
运行结果:
例2:验证NEW、RUNNABLE和TERMINATED
public class Run2 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (int i = 0; i < 1000_0000; i++) {
}
}, "李四");
System.out.println(t.getName() + ": " + t.getState());;
t.start();
while (t.isAlive()) {
System.out.println(t.getName() + ": " + t.getState());;
}
System.out.println(t.getName() + ": " + t.getState());;
}
}
运行结果:
李四: NEW
…
李四: RUNNABLE
…
李四: TERMINATED
例3:验证 WAITING 、 BLOCKED 、 TIMED_WAITING
public class Run3 {
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
Thread t = new Thread(() -> {
synchronized (object) {
try {object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 1000_0000; i++) {
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(t.getState());;
t.start();
System.out.println(t.getState());
Thread.sleep(10);
synchronized (object) { for (int i = 0; i < 10; i++) {
System.out.println(t.getState());
}
object.notify();
}
while (t.isAlive()) {
System.out.println(t.getState());
}
}
}
运行结果:
例4: yield() 大公无私,让出 CPU
public class Run4 {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + ": 我跑着呢");
// Thread.yield();
}
}, "李四");
Thread thread2 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + ": 我跑着呢");
}
}, "王五");
thread1.start();
thread2.start();
}
}
运行结束:
- yield() 只是让出 CPU,并不会改变自己的状态。也就上面途中,我从柜台前站起,又重新去排队去了
- 因为李四总是无私的让出座位,王五并不让座位,所以会导致王五打印的更多。
例5:验证TIMED_WAITING
//线程状态TIMED_WAITING代表线程执行了Thread.sleep()方法,呈等待状态,等待时间到达,然后继续向下运行。
//执行sleep()方法后线程的状态枚举值就是TIMED_WAITING。
class Mythread2 extends Thread{
@Override
public void run() {
try{
System.out.println("begin sleep");
Thread.sleep(1000);
System.out.println("end sleep");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Run5 {
public static void main(String[] args) {
try{
Mythread2 mythread2=new Mythread2();
mythread2.start();
Thread.sleep(1000);
System.out.println("main方法中的状态: "+mythread2.getState());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
运行结果:
例6:验证BLOCKED
//BLOCK状态出现在某个线程在等待锁的时候。
//从运行结果来看mythread32线程一直在等待mythread31对锁进行释放,所以mythread32当时处于BLOCKED状态。
class MyService{
synchronized static public void serviceMethod(){
try{
System.out.println(Thread.currentThread().getName()+"进入了业务方法");
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class MyThread31 extends Thread{
@Override
public void run() {
MyService.serviceMethod();
}
}
class MyThread32 extends Thread{
@Override
public void run() {
MyService.serviceMethod();
}
}
public class Run6 {
public static void main(String[] args) throws InterruptedException{
MyThread31 mythread31=new MyThread31();
mythread31.setName("a");
mythread31.start();
Thread.sleep(1000);
MyThread32 mythread32=new MyThread32();
mythread32.setName("b");
mythread32.start();
Thread.sleep(1000);
System.out.println("main方法中没有thread21状态:"+mythread32.getState());
}
}
运行结果:
例7:验证WAITING
//WAITING状态是线程执行了Object.wait()方法后所处的状态。
//执行wait()方法后线程状态枚举值就是WAITING。
class Lock{
static final Byte lock=new Byte("0");
}
class Mythread7 extends Thread{
@Override
public void run() {
try {
synchronized (Lock.lock){
Lock.lock.wait();
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Run7 {
public static void main(String[] args) {
try{
Mythread7 mythread7=new Mythread7();
mythread7.start();
Thread.sleep(1000);
System.out.println("main方法中的mythread7状态: "+mythread7.getState());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
运行结果: