3.Java线程的状态

发布于:2023-01-05 ⋅ 阅读:(449) ⋅ 点赞:(0)

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状态不仅不释放已经占有的资源,还在等待其他资源。


网站公告

今日签到

点亮在社区的每一天
去签到