Java线程生命周期概要

本文详细介绍了Java线程的生命周期,包括新建、可运行、运行、阻塞和死亡五种状态。重点讨论了阻塞状态的三种类型:等待阻塞、同步阻塞和其他阻塞,涉及线程同步、wait/notify机制及sleep、join方法。理解线程状态对于优化并发编程至关重要。
摘要由CSDN通过智能技术生成

线程的生命周期

首先,让我们根据一张图来了解一下线程的生命周期.
在这里插入图片描述

线程的生命周期包括五个状态:

  • 新建状态New

    新建状态是在线程实例在被创建之后但是还没调用start()方法之前所处的状态,不做深入研究.

  • 可运行状态Runnable

    此时线程已经调用了start(),但是因为没有被CPU调度,即没有获得CPU运行时间片,所以只是处于可运行状态,并未真的运行.

  • 运行状态Running

    线程获得了CPU时间片,开始执行线程体的内容.

  • 阻塞状态Blocked

    线程的阻塞状态是线程最复杂的一个状态,因为一个线程可能因为多种原因被阻塞.在这里我们先从线程运行的条件讲起.

    若线程中没有同步代码块,则线程无需关心对象锁的获取,此时线程可能被阻塞的原因有:

    • 线程被操作系统调度出CPU,比如线程进行IO耗时操作
    • 调用Thread.sleep(),该方法会导致线程休眠,从而释放CPU资源
    • 线程调用了其他线程的join方法,此方法会等待join方法的调用线程完全执行结束后才继续执行当前线程,从而导致当前线程阻塞
    • 当前线程调用yield方法,导致线程释放CPU而进入可执行状态.

    若线程中有同步代码块,则线程要运行必须同时满足获得同步代码块所需对象锁以及CPU资源两个条件,此时被阻塞的原因除了上面原因以外,还包括:

    • 线程尝试获取对象锁失败从而阻塞
    • 线程在执行过长中调用了同步对象的wait()方法,主动释放CPU资源以及对象锁,从而阻塞.

    结合以上两种情况,一个线程被阻塞的情况由大概有三种:

    1. 等待阻塞

      在当前线程已经获得对象锁以及CPU的前提下,调用同步对象的wait()方法,从而导致当前线程释放CPU,释放对象锁,将当前线程放入同步对象的waitSet集合中.

      waitSet中的阻塞线程只有通过同步对象调用notifynotifyAll方法才能再次被唤醒,唤醒后进入可执行状态.

    2. 同步阻塞

      当前线程在运行到同步代码块时,尝试获取同步对象的对象所失败而被放入该对象的entrySet,即我们说的锁池集合中.

      entrySet中的线程等待获取同步对象的锁然后进入可运行状态.一切释放锁的操作都可能唤醒里面的线程,如:

      • 持有同步对象锁的线程退出同步代码块(执行结束等)
      • 同步对象调用wait(),该方法会释放CPU和锁
    3. 其他阻塞

      当前线程调用Thread.sleep(long millis)方法,导致当前线程休眠,此操作会释放CPU,但是已经持有的对象锁不会释放.

      同样的还有在线程a中调用线程b.join()方法,该方法导致a会等待b执行完毕之后才会继续执行,a会让出CPU资源,但不确定join是否释放锁.

      join的底层实现仍是wait,详细请参考Join()会不会释放锁?

在这里插入图片描述

线程因为满足运行条件而从这三个阻塞状态中解脱出来时都会被放到Runnable队列中等待系统调度.

  • 死亡状态Dead

    线程执行结束后的状态.值得一说的是,线程也是一个对象,也有对象锁,在线程退出的时候会主动调用自己的notify函数来调用在自己waitSet里面的线程.

wait会释放锁,释放的前提是已经获得了锁,所以必须要在sychronized同步代码块中调用wait,不然就相当于在不确定是否获得锁的情况下去释放锁,这也是有问题的.

sychronized-wait-notify是配套使用的,设计目的是为了完成线程间通信.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值