Java中的线程状态

线程状态

关于Java中的线程状态,去网上找相关资料发现说法并不相同。虽然不同语言中的线程中的线程状态大同小异,但是在Java中存在的线程状态只有六种。这六种线程状态在「Thread」类中有说明,在Thread类中有一个「State」枚举,该枚举中定义了Java中线程的状态。

New

如果一个线程刚被创建出来还未启动,那么该线程就处于该状态。

Thread t1 = new Thread();
log.info("t1 = {}",t1.getState());

RUNNABLE

可运行线程的线程状态。处在可运行状态的线程正在Java虚拟机中执行,但是它可能正在等待来自操作系统的其他资源,主要是指CPU资源。

Thread t2 = new Thread(() -> {
    while (true){}
});
t2.start();
log.info("t2 = {}",t2.getState());

BLOCKED

受阻塞并等待某个监视锁的线程就处于该状态。处于受阻塞状态的某一线程正在等待监视器锁,以便进入一个同步的代码块或者方法。

        Object o = new Object();
        Thread t3 = new Thread(() ->{
            synchronized (o){
                while (true){

                }
            }
        });
        Thread t4 = new Thread(() ->{
            synchronized (o){
                while (true){

                }
            }
        });
        t3.start();
        t4.start();
        //增加1s延时,如果不添加可能线程还没启动看不到处于BLOCKED的线程状态
        Thread.sleep(1000);
        log.info("t3 = {},t4 = {}",t3.getState(),t4.getState());

例如上面状态的代码,线程t3和t4都在争夺实例对象「o」的监视锁,但是只有一个线程能获取成功。所以最后的结果是一个处于RUNNABLE状态,另一个则处于BLOCKED状态。

WAITING

某一等待线程的线程状态。简单的说就是处于等待状态的线程正在等待另一线程,以执行特定操作。通常在下面情况下线程会进入等待状态:

  • 不带超时值的Object.wait
  • 不带超时值的Thread.join
  • LockSupport.park
        Object syncObject = new Object();
        Thread t5 = new Thread(()->{
            synchronized (syncObject){
                try {
                    syncObject.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t5.start();
        Thread.sleep(1000);
        
        Thread t6 = new Thread(()->{
            synchronized (syncObject){
                try {
                    log.info("t5 = {},t6 = {}",t5.getState(),Thread.currentThread().getState());
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                syncObject.notify();
            }
        });
        t6.start();

上面代码中有两个线程t5和t6,还有一个同步对象syncObject。t5先获取到同步对象进入同步代码块,接着代码t5线程调用同步对象的wait方法,释放掉同步对象t6获取到锁。这时打印出t5和t6线程的状态分别为「WAITING」「RUNNABLE」

        Thread t7 = new Thread(() -> {
            Thread t8 = new Thread(() ->{
                while (true){}
            });
            t8.start();
            try {
                log.info("t8调用join");
                t8.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t7.start();
        Thread.sleep(1500);
        log.info("t7 = {}",t7.getState());

上面的代码,线程t7内创建线程t8然后启动线程t8,t8启动后调用t8.join,这样线程t7就不能直接退出必须等待线程t8执行之后才会退出,而这个时候的线程状态就是「WAITING」

        Thread t9 = new Thread(() ->{
            log.info("LockSupport 前:{}",Thread.currentThread().getState());
            LockSupport.park();
            log.info("LockSupport执行完成后");
        });
        t9.start();
        Thread.sleep(1000);
        log.info("t9 = {}",t9.getState());
        LockSupport.unpark(t9);
        log.info("调用unpark t9");

线程t9启动后内部调用 「LockSupport.park()」 方法后进入waiting状态。然后通过在主线程中打印出线程t9的状态,最后调用「LockSupport.unpark(t9)」

TIMED_WAITING

具有指定等待时间的某一等待线程的线程状态。与WAITING类似,不同的在于WAITING没有指定时间。在触发方法上多了Thread.sleep方法。

TERMINATED

已终止线程的线程状态。如果线程处于该状态说明线程已执行完成。

        Thread t10 = new Thread(() -> log.info("t10执行完毕!"));
        t10.start();
        t10.join();
        log.info("t10 = {}",t10.getState());

小结

Java中的线程只会处于上述的六种状态,其他状态比较好区分,不太好区分的是WAITING和BLOCKED状态。这两个状态的本质区别在于:

  • BLOCKED是线程因为缺少锁而导致进入的阻塞,它的阻塞是因为缺少资源。
  • 而WAITING不是因为缺少资源,而是它需要等待另外一个线程的特定操作。通常来说需要等待另一线程的notify或者notifyAll操作。
Java中的线程状态
JAVA线程状态

借用网上的一张图,该图完整的展示了Java线程的各种状态以及各种状态的转换规则。详细了解线程的状态,这个对于dump线程线程很重要,也有利于多线程其他知识的学习。


原文始发于微信公众号(一只菜鸟程序员):Java中的线程状态

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73058.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!