Java线程的六大状态
在Java并发编程的面试中,多线程的问题几乎是必问的,而有一个送分题但却最容易因为细节而丢分——“请说说Java线程的生命周期”。
大多数人都能脱口而出‘新建,运行,阻塞,死亡’,但这其实是操作系统的线程状态,而不是Java语言层面的答案,在Java对于线程引用提供的方法 getState( ) 的枚举中,线程其实还有更细节的六大状态
还有观察线程各种状态的小工具——jconsole(Java Monitoring and Management Console(Java 监控与管理控制台))
接下来,我们一一介绍:
一、NEW
安排了工作,但还未开始行动
new出了实例对象,但还未start(),我们可以通过代码观察:
public class demo1 {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("1");
});
System.out.println(t1.getState());
t1.start();
}
}
发现 t1.getState() 的结果为 NEW
二、RUNNABLE
可工作的,又可以分为正在工作中或即将开始工作
我们设计一个死循环,循环体内什么都不执行,但线程处于死循环内本身也是一种执行,所以我们预期 t1.getState( ) 的结果为RUNNABLE
代码实例:
public class State {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while(true){
}
});
t1.start();
System.out.println(t1.getState());
}
}
三、TERMINATED
工作已完成
设计一串代码,保证计算机可以快速执行这个线程到完毕,在线程start后,我们sleep(3000)睡个一秒来保证线程执行完毕,随后通过 t1.getState( ) 来观察打印结果
代码实例:
public class State {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
System.out.println("1");
});
t1.start();
Thread.sleep(3000);
System.out.println(t1.getState());
}
}
四、TIMED_WAITING
线程此时正处于一种阻塞状态,这个线程正在排队中,非死等,阻塞的时间有上限
我们设计一个死循环,循环体内加上一条 Thread.sleep(1000),线程每执行一次循环体内的内容就会阻塞1000毫秒,而计算机的执行速度非常之快,可能执行循环体内的内容只需要几毫秒甚至更短,所以绝大部分时间都因为 sleep 的缘故处于一种阻塞状态,所以我们简单设计的代码绝
大概率是能通过 t1.getState( ) 来得到想要的 TIMED_WAITING的
代码实例:
public class State {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
Thread.sleep(1000);
System.out.println(t1.getState());
}
}
我们设计start后,先让主线程睡一秒,再观察t1线程的状态,如果不睡这一秒,主线程会在t1.start之后迅速观察并打印t1线程的状态,t1线程此时的状态大概率还未第一次执行到sleep,所以我们很可能会观察到RUNNABLE,所以我们设计先睡上这一秒以便我们观察
五、WAITING
线程此时处于一种阻塞状态,正在排队中,而且是一种没有时间上限的死等,永远处于阻塞状态
这次我们不观察t1的状态,而是这样设计:让t1线程执行死循环代码,让main线程死等t1线程执行完后再执行自身代码,此时观察main线程的状态
代码实例:
Thread main = Thread.currentThread();
Thread t1 = new Thread(()->{
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t1.join();
System.out.println(main.getState());
❌️❌️❌️ 如果main要等t1线程执行完,可能这辈子都无法在编译软件里看到main的状态了,因为t1.join( ) 是main线程对t1线程的无限的等待,永远无法执行到打印main线程的状态。
✅️✅️✅️ 我们通过 jdk 的bin目录中的一个名为 jconsole.exe 的软件来观察线程的状态,什么是jconsole?全名:Java Monitoring and Management Console(Java 监控与管理控制台)
这是我们观察线程状态的好工具

我们点开后选中并连接代码所在的类State中,选择左上角的线程

我们观察main线程的状态——WAITING,正是我们想要的结果✅️
⚠️如果是第一次用需要注意⚠️:
这里没有t1线程的名字是因为我们的引用叫t1,但线程的名字不是t1,我们没有给这个线程取名字,所以编译器默认给这个线程取名叫 Thread-0——这就是我们的t1线程,我们可以点一下看看

上述我们的TIMED_WAITING讲到,t1线程绝大部分时间处于sleep(1000)这1000毫秒里,所以t1线程处于一种有时间上限的等待的阻塞状态,我们也发现其状态确实如此✅️
更多推荐

所有评论(0)