847 字
4 分钟
线程的生命周期

线程的生命周期#

线程状态流程图

image

  • NEW:创建状态,线程创建之后,但是还未启动。
  • RUNNABLE:运行状态,处于运行状态的线程,但有可能处于等待状态,例如等待CPU、IO等。
  • WAITING:等待状态,一般是调用了wait()、join()、LockSupport.spark()等方法。
  • TIMED_WAITING:超时等待状态,也就是带时间的等待状态。一般是调用了wait(time)、join(time)、LockSupport.sparkNanos()、LockSupport.sparkUnit()等方法。
  • BLOCKED:阻塞状态,等待锁的释放,例如调用了synchronized增加了锁。
  • TERMINATED:终止状态,一般是线程完成任务后退出或者异常终止。

NEW、WAITING、TIMED_WAITING都比较好理解,我们重点说一说RUNNABLE运行态和BLOCKED阻塞态。

线程进入RUNNABLE运行态一般分为五种情况:

  • 线程调用sleep(time)后结束了休眠时间
  • 线程调用的阻塞IO已经返回,阻塞方法执行完毕
  • 线程成功的获取了资源锁
  • 线程正在等待某个通知,成功的获得了其他线程发出的通知
  • 线程处于挂起状态,然后调用了resume()恢复方法,解除了挂起。

线程进入BLOCKED阻塞态一般也分为五种情况:

  • 线程调用sleep()方法主动放弃占有的资源
  • 线程调用了阻塞式IO的方法,在该方法返回前,该线程被阻塞。
  • 线程视图获得一个资源锁,但是该资源锁正被其他线程锁持有。
  • 线程正在等待某个通知
  • 线程调度器调用suspend()方法将该线程挂起

我们再来看看和线程状态相关的一些方法。

  • sleep()方法让当前正在执行的线程在指定时间内暂停执行,正在执行的线程可以通过Thread.currentThread()方法获取。

  • yield()方法放弃线程持有的CPU资源,将其让给其他任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。

  • wait()方法是当前执行代码的线程进行等待,将当前线程放入预执行队列,并在wait()所在的代码处停止执行,直到接到通知或者被中断为止。该方法可以使得调用该方法的线程释放共享资源的锁, 然后从运行状态退出,进入等待队列,直到再次被唤醒。该方法只能在同步代码块里调用,否则会抛出IllegalMonitorStateException异常。wait(long millis)方法等待某一段时间内是否有线程对锁进行唤醒,如果超过了这个时间则自动唤醒。

  • notify()方法用来通知那些可能等待该对象的对象锁的其他线程,该方法可以随机唤醒等待队列中等同一共享资源的一个线程,并使该线程退出等待队列,进入可运行状态。

  • notifyAll()方法可以使所有正在等待队列中等待同一共享资源的全部线程从等待状态退出,进入可运行状态,一般会是优先级高的线程先执行,但是根据虚拟机的实现不同,也有可能是随机执行。

  • join()方法可以让调用它的线程正常执行完成后,再去执行该线程后面的代码,它具有让线程排队的作用。

线程的生命周期
作者
强人自传
发布于
2023-03-31
许可协议
CC BY-NC-SA 4.0