线程状态定义
Thread里面关于线程状态的定义:
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
先看一个线程的状态图:
NEW,TERMINATED
线程对象刚创建,还未执行start方法前的状态为NEW,初始状态;在线程执行完run方法里面的内容后的状态为TERMINATED,终止状态,线程已经执行完退出。
我们在JVM中监控线程时,这两个状态是看不到的。
RUNNABLE
线程对象执行完start方法后的状态,细分为Ready和Running两个形态,线程在抢到CPU时间片时,处于Running运行状态,执行run方法中的代码;
在未抢到CPU时间片或CPU时间片被操作系统分配给了其它线程时,线程处于Ready状态,等待获取CPU时间片执行线程。
BLOCKED
运行中的线程,在遇到synchronized代码块或方法时,等待获取锁对象时的状态,此状态表示线程不具备CPU执行资格,也没有CPU执行权限。
故此状态不占用CPU资源,等待获取对象锁后,线程再进入Ready状态。
本状态属于阻塞状态的一种,即等待获取锁对象时被阻塞。
WAITING
运行中的线程,在执行以下方法Object.wait()、 Thread.join()、LockSupport.park()时,状态由RUNNABLE变为WAITING。
此时线程不再占用CPU资源,直到被notify()后,再进入Ready状态,等待抢夺获取CPU时间片。
本状态属于阻塞状态的一种,即等待另一个线程执行某种操作之后,再继续执行自身线程。
下面为WAITING状态的代码:
class QueMsg{
private int num = 0;
public int getNum() {
return num;
}
public synchronized int consumeMsg(){
if(num>0) {
return num--;
}else{
return 0;
}
}
public void addMsg(int num){
this.num += num;
}
}
public void testWaiting(){
QueMsg msg = new QueMsg();
Thread consumer_a = new Thread(()->{
while(msg.getNum() == 0){
try {
synchronized (msg) {
msg.wait();
}
}catch(Exception e){
e.printStackTrace();
}
int m = msg.consumeMsg();
if(m>0) {
System.out.println("Consumer-A 当前状态:"+Thread.currentThread().getState()+" ---收到一条消息:" + m + " 退出");
break;
}
}
}, "Consumer-A");
Thread consumer_b = new Thread(()->{
while(msg.getNum() == 0){
try {
synchronized (msg) {
msg.wait();
}
}catch(Exception e){
e.printStackTrace();
}
int m = msg.consumeMsg();
if(m>0) {
System.out.println("Consumer-B 当前状态:"+Thread.currentThread().getState()+" ---收到一条消息:" + m + " 退出");
break;
}
}
}, "Consumer-B");
Thread producer = new Thread(()->{
try {
Thread.currentThread().sleep(10L);
}catch(Exception e){
e.printStackTrace();
}
msg.addMsg(1);
System.out.println("Producer-C 发送一条消息,当前消息数量:"+msg.getNum());
synchronized (msg) {
msg.notifyAll();
}
try {
Thread.currentThread().sleep(20L);
}catch(Exception e){
e.printStackTrace();
}
msg.addMsg(1);
System.out.println("Producer-C 发送一条消息,当前消息数量:"+msg.getNum());
synchronized (msg) {
msg.notifyAll();
}
}, "Producer-C");
System.out.println("Consumer_A创建后的状态:"+consumer_a.getState());
System.out.println("Consumer_B创建后的状态:"+consumer_b.getState());
consumer_a.start();
System.out.println("Consumer_A在调用start后的状态:"+consumer_a.getState());
consumer_b.start();
System.out.println("Consumer_B在调用start后的状态:"+consumer_b.getState());
producer.start();
try {
Thread.currentThread().sleep(5L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("--------------------------------------");
System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
try {
Thread.currentThread().sleep(10L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("--------------------------------------");
System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
try {
Thread.currentThread().sleep(40L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("--------------------------------------");
System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
}
运行结果:
Consumer_A创建后的状态:NEW
Consumer_B创建后的状态:NEW
Consumer_A在调用start后的状态:RUNNABLE
Consumer_B在调用start后的状态:RUNNABLE
--------------------------------------
Consumer_A 当前的状态:WAITING
Consumer_B 当前的状态:WAITING
Producer-C 发送一条消息,当前消息数量:1
Consumer-B 当前状态:RUNNABLE ---收到一条消息:1 退出
--------------------------------------
Consumer_A 当前的状态:WAITING
Consumer_B 当前的状态:TERMINATED
Producer-C 发送一条消息,当前消息数量:1
Consumer-A 当前状态:RUNNABLE ---收到一条消息:1 退出
--------------------------------------
Consumer_A 当前的状态:TERMINATED
Consumer_B 当前的状态:TERMINATED
进程已结束,退出代码 0
TIMED_WAITING
运行中的线程,在执行以下方法Object.wait(long),、Thread.sleep(long)、 Thread.join(long)、LockSupport.parkNanos()、LockSupport.parkUntil()时,状态由RUNNABLE变为TIMED_WAITING。
此时线程不再占用CPU资源,直到到了超时时间或被notify()后,再进入Ready状态,等待抢夺获取CPU时间片。
本状态属于阻塞状态的一种,即等待另一个线程执行某种操作之后,再继续执行自身线程。
下面为NEW、RUNNABLE、BLOCKED、WAITING、TERMINATED状态的代码
@Test
public void testStates(){
Thread tha = new Thread(()->{
try {
Thread.sleep(30L);
}catch (Exception e){
e.printStackTrace();
}
syncMethod();
}, "Thread-A");
Thread thb = new Thread(()->{
syncMethod();
}, "Thread-B");
System.out.println("Thread-A 线程刚创建后的状态 : " +tha.getState());
tha.start();
thb.start();
System.out.println("Thread-A 线程执行start方法后的状态 : "+tha.getState());
try {
Thread.sleep(40L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Thread-A 线程等待执行ayncMehtod时的状态 : "+tha.getState());
try {
Thread.sleep(30L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Thread-A 线程执行asyncMehtod后线程等待50S时的状态 : "+tha.getState());
try {
Thread.sleep(60L);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Thread-A 线程运行结束后的状态 : "+tha.getState());
}
private synchronized void syncMethod(){
System.out.println("----" + Thread.currentThread().getName() + " 线程获取到方法锁");
try {
Thread.sleep(50L);
}catch(Exception e){
e.printStackTrace();
}
}
运行结果:
read-A 线程刚创建后的状态 : NEW
Thread-A 线程执行start方法后的状态 : RUNNABLE
----Thread-B 线程获取到方法锁
Thread-A 线程等待执行ayncMehtod时的状态 : BLOCKED
----Thread-A 线程获取到方法锁
Thread-A 线程执行asyncMehtod后线程等待50S时的状态 : TIMED_WAITING
Thread-A 线程运行结束后的状态 : TERMINATED
进程已结束,退出代码 0
线程状态分类图
线程状态转换
总结
通过以上的说明,样例及图示,我们对线程的状态种类、状态分类、状态的转换已经有了很清晰的认识。
同时,也比较明确,NEW和TERMINATED状态,在现实场景中,很难看到;
RUNNABLE状态的线程是会占用CPU资源的;
BLOCKED和TIMED_WAITING以及WAITING状态,均为阻塞状态,其中BLOCKED状态为资源锁等待,
TIMED_WAITING和WAITING为等待另一个线程执行结果的状态等待,他们均不占用CPU资源,但BLOCKED是会存在耗时及并发等待的。