3.Java线程的状态

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.Java线程的状态相关的知识,希望对你有一定的参考价值。

1 Java线程的6种状态

在单线程环境下,线程的生命周期就是“创建、执行和终止”,但是在多线程环境下就不能这么分了。

Java的线程有6种基本的方式,如下:

  • New:初始状态,线程被构建,但是还没有调用start()方法。

  • Runnable:运行状态,Java线程将操作系统的就绪和运行两种状态笼统的地称作“运行中”。

  • Blocked:阻塞状态,当线程执行了synchronized代码,并且没有抢到锁时就会变成该状态。

  • WAITING:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程通知或者中断。

  • TIME_WAITING:超时等待状态,该状态与WAITING是不同的,该状态可以再指定的时间自行返回。

  • TERMINED:终止状态,表示当前线程已经执行完毕、

在这个过程中,Blocked和waing什么区别呢?导致blocked只有一种情况,就是锁等待(Synchronized),这两者没有本质的区别,理解为定义或者发生的背景不一样就行了。

这几种状态之间的转换关系是:

上图中lockSupport用来创建lock锁的基本线程阻塞单元。LockSupport提供的是一个许可,如果存在许可,线程在调用park的时候会立马返回,此时许可会立马被消费掉,如果没有许可,则会阻塞。

下面我们使用多个例子来进一步演示几种状态。

2. 阻塞状态

阻塞状态是一种特殊的状态,WAITING,TIME_WAITING,BLOCKED都属于阻塞状态,IO也会引起阻塞状态。 阻塞状态也不止一种情况,有waiting,time_waiting,blocked,io阻塞等 。我们现在就用多个例子来演示一下。

TIME_WAITING状态

public class TimedWaitingStatusExample 
    public static void main(String[] args) 
        new Thread(() -> 
            try 
                TimeUnit.SECONDS.sleep(10000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        , "TIME_WAITING").start();
    

运行之后 ,我们使用jstack看一下堆信息,其中有如下一段内容:

这里,我们可以看到线程的状态就是TIMED_WAITING状态,也就是sleeping状态。

WAITING状态

public class WaitingStatusExample 
    public static void main(String[] args) 
        new Thread(()->
            synchronized (WaitingStatusExample.class)
                try 
                    WaitingStatusExample.class.wait();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        ,"WAITING").start();
    

我们同样使用jstack看一下其状态:

 我们可以看到WAITING和TIME_WAITING是不一样的,TIME_WAITING就是在sleep,而WAITING则是一致在等待资源(on object monitor)。

Blocked状态

我们再看Blocked状态的例子:

public class BlockedStatusExample implements Runnable 
    public static void main(String[] args) 
        new Thread(new BlockedStatusExample(), "BLOCKED_T1").start();
        new Thread(new BlockedStatusExample(), "BLOCKED_T2").start();
    
​
    @Override
    public void run() 
        synchronized (BlockedStatusExample.class) 
            //一直不释放锁
            while (true) 
            
        
    

此时使用jstack查看进程的状态为:

 此时我们可以看到BLOCKED_T1抢到了资源,状态为Runnable,而BLOCKED_T2没有抢到锁,状态为监听状态。

而且对比发现BLOCKED_T2的监听状态与上面WAITING的状态基本一致的,这就说明两种状态本质上是一致的,只不过触发的条件不一样罢了。

结论就是:TimeWaiting状态就是sleep状态,会释放占有的资源。而waiting和Blocked状态不仅不释放已经占有的资源,还在等待其他资源。

以上是关于3.Java线程的状态的主要内容,如果未能解决你的问题,请参考以下文章

DatagramSocket类 会发生线程阻塞的方法

《Java并发编程实战》第三章 对象的共享 读书笔记

3.java内存模型以及happens-before规则

当一个线程试图访问一个互斥锁资源时会发生啥?

对象的共享

3.java并发编程艺术-java内存模型