Java-多线程-线程状态

左手的ㄟ右手 2023-07-20 12:30 35阅读 0赞

Java-多线程-线程状态

1 简介

Java线程并不是和Linux线程完全对等的,每个Java线程拥有NEW(新建)、RUNNABLE(就绪)、BLOCKED(阻塞)、WAITING(等待)、TIMED WAITING(计时等待)、TERMINATED(终止)。

Java线程调度属于抢占式调度,线程竞争CPU时间分片来执行,一个线程运行几十毫秒中就处于RUNNING状态,而时间片用完了被剥夺CPU资源又处于READY状态了,等待下次调度。

2 线程状态

在这里插入图片描述
在这里插入图片描述

  1. NEW(新建)
    使用 new Thread(new Runnable) 类或其子类建立一个线程对象后,该线程对象就处于新建状态。

    此时线程还未执行,一般是在构造方法中做一些初始化工作。

    NEW状态的线程只能在thread.start()方法之后转为RUNNABLE状态。

  2. RUNNABLE(就绪)
    NEW状态的线程调用了thread.start()方法之后,该线程就进入RUNNABLE状态,等待JVM里线程调度器的调度,此时处于READY就绪状态。

    当获得CPU时间片后,线程开始执行,线程处于RUNNING运行状态。时间片用完后,线程被剥夺运行资格,等待下一次运行,又变为就绪状态。也就是说,此状态下不能保证线程是就绪还是正在运行。

  3. BLOCKED(阻塞)
    RUNNABLE状态线程申请被其他线程持有的对象锁,此时就转为BLOCKED状态,此时线程不运行任何代码且消耗最少的资源,直到线程调度器重新激活运行该线程。

    当其他线程释放该对象锁后,如果本线程竞争到了对象锁,就转回RUNNABLE状态。

  4. WAITING(无期限等待)
    如果一个线程A等待另一个线程给与调度器一个条件时,线程A进入WAITING状态,等待被其他线程notify唤醒。

    如调用Object.waitThread.joinjava.util.concurrent中的Lock或Condition等。

    条件发生后,就转回RUNNABLE状态。(如果是wait方法进入的等待状态,被notify唤醒后进入对象锁同步队列重新竞争锁,竞争到了就进入RUNNABLE状态,竞争失败就进入BLOCKED状态)

  5. TIMED WAITING(计时等待)
    以上方法有一些带有时间参数的重载方法(如Object.waitThread.joinjava.util.concurrent中的Lock.tryLock、Condition.await),就会进入TIMED WAITING状态

    1. 条件发生后,就转回`RUNNABLE`状态(如果是wait方法进入的等待状态,被notify唤醒后进入对象锁同步队列重新竞争锁,竞争到了就进入RUNNABLE状态,竞争失败就进入BLOCKED状态)。
  6. TERMINATED(终止)
    线程run方法结束或抛出了未捕获的异常导致结束。

    在一个TERMINATED的线程上调用start()方法会抛出java.lang.IllegalThreadStateException异常。

3 相关方法

  • Thread.sleep(long millis)
    由当前线程调用此方法,调用后进入TIMED_WAITING状态,但不释放对象锁。millis期满后线程自动唤醒进入RUNNABLE状态。
  • Thread.yield(),
    由当前线程调用此方法,给CPU提示表示当前线程愿意放弃获取的CPU时间片(调度器可忽略该提示),但不释放对象锁。如果成功释放时间片则该线程由运行状态变为就绪状态,由调度器再次选择线程进行调度执行。

    • Sleep对比Yield
      主要是使用场景不同。Sleep主要用来指定睡眠时间让出CPU,并在时间到后再被系统分配CPU资源,进行调度执行;而Yield是用来主动释放CPU给其他线程执行,但无法精确控制是否释放。
  • t.join()/t.join(long millis),
    join方法主要用来等待其他线程运行结束,再继续运行自己的线程代码。

    当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。

    等到线程t执行完毕或者millis时间到,当前线程重新进入RUNNABLE状态。

  • obj.wait()
    当前线程调用对象的wait()方法,当前线程会释放该对象锁,并进入等待队列等待其他竞争到锁的线程执行完后唤醒,重新进入等待队列进行锁竞争,竞争成功后才会从wait方法返回。

    注意这个wait方法只会让该线程释放当前Object的对象锁,而不会放弃拥有的其他对象锁!

  • obj.wait(mills)
    当前线程调用对象的wait()方法,当前线程会释放该对象锁,并进入等待队列等待其他竞争到锁的线程执行完后唤醒或时间耗尽,重新进入等待队列进行锁竞争,竞争成功后才会从wait方法返回。

    注意这个wait方法只会让该线程释放当前Object的对象锁,而不会放弃拥有的其他对象锁!

  • obj.notify()
    该方法用来任意唤醒一个在对象锁的等待集的线程(其实看了源码会发现不是任意的,而是一个WaitQueue,FIFO)。
  • obj.notifyAll()
    唤醒在此对象Monitor上等待的所有线程。

4 线程优先级

很多操作系统都提供线程优先级的概念,但是由于平台特性的问题,Java中的线程优先级和不同平台中系统线程优先级并不匹配,所以Java线程优先级可以仅仅理解为“建议优先级”,通俗来说就是java.lang.Thread#setPriority(int newPriority)并不一定生效,有可能Java线程的优先级会被系统自行改变。

参考文档

  • Java线程的6种状态及切换(透彻讲解)
  • Java-多线程-Thread相关方法
  • Java-并发-关于锁的一切
  • Java-多线程-wait/notify
  • java线程运行怎么有第六种状态?
  • Java线程中wait状态和block状态的区别?
  • Java线程生命周期与状态切换

发表评论

表情:
评论列表 (有 0 条评论,35人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java 线状态

    Java 多线程是 Java 语言中的一项重要功能,它允许程序在同一时间内运行多个线程,从而提高程序的并发性能。在 Java 多线程中,线程状态是一个非常重要的概念,它表示线程

    相关 Java线 —— 线状态迁移

    引言 线程状态迁移,又常被称作线程的生命周期,指的是线程从创建到终结需要经历哪些状态,什么情况下会出现哪些状态。 线程的状态直接关系着并发编程的各种问题,本文就线程的状