操作系统线程和Java线程的状态

操作系统线程和Java线程的状态

   一、操作系统线程的状态

   操作系统的线程主要有以下三个状态

   1.  就绪状态(ready):线程正在等待使用 CPU,经调度程序调用之后进入 running 状态。

   2. 执行状态(running):线程正在使用 CPU。

   3. 等待状态(waiting): 线程经过等待事件的调用或者正在等待其他资源(如 I/O)。

   二、Java中线程的状态

   Java中线程的状态分为6种。

1 // Thread.State 源码
2 public enum State {
3     NEW,
4     RUNNABLE,
5     BLOCKED,
6     WAITING,
7     TIMED_WAITING,
8     TERMINATED;
9 }

   1.  初始状态(New

   当线程对象被创建但尚未启动时,处于新建状态

   示例代码如下:

1 private void testStateNew() {
2     Thread thread = new Thread(() -> {});
3     System.out.println(thread.getState()); // 输出 NEW
4 }

   2. 可运行状态 (RUNNABLE)

   表示当前线程正在运行中。处于 RUNNABLE 状态的线程在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源。

   说明:

   1)Java 线程的RUNNABLE状态其实包括了操作系统线程的就绪(ready)和运行中(running)两个状态

   2)线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

   3.  阻塞状态(BLOCKED

   阻塞状态。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区。

   说明:一个线程获取一个内部的对象锁的时候这个锁对象被其他线程占用了,那么这个线程就会被阻塞。是一种锁阻塞

   4. 等待状态 (WAITING)

   进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。

   调用下面这 3 个方法会使线程进入等待状态:

   1)Object.wait():使当前线程处于等待状态直到另一个线程唤醒它

   2)Thread.join():等待线程执行完毕,底层调用的是 Object 的 wait 方法

   3)LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度

   5.  超时等待(TIMED_WAITING)

   超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。

   调用如下方法会使线程进入超时等待状态:

   1)Thread.sleep(long millis):使当前线程睡眠指定时间

   2)Object.wait(long timeout):线程休眠指定时间,等待期间可以通过notify()/notifyAll()唤醒

   3)Thread.join(long millis):等待当前线程最多执行 millis 毫秒,如果 millis 为 0,则会一直执行

   4)LockSupport.parkNanos(long nanos): 除非获得调用许可,否则禁用当前线程进行线程调度指定时间

   5)LockSupport.parkUntil(long deadline):同上,也是禁止线程进行调度指定时间

   说明:处于这种状态的线程也不会被分配CPU执行时间,不过无须等待被其他线程显式地唤醒,在一定时间之后它们会由操作系统自动唤醒。

   6.  终止状态(TERMINATED)

   线程执行完毕或者因为异常退出而终止时处于该状态。

   说明:

   1)终止状态为了两种情况,一种就是我们调用run方法,正常执行完毕,线程自然终止。

   2)因为一个没有捕获的异常终止了run方法,使线程意外终止。

   3)一旦进入终止状态,线程将不再拥有运行的资格,也不能再转换到其他状态,生命周期结束。

   三、Java中线程状态的转换

   线程状态转换图如下:

    1.  WAITING 状态与 RUNNABLE 状态的转换

    根据上图我们知道有 3 个方法可以使线程从 RUNNABLE 状态转为 WAITING 状态。我们主要介绍下Object.wait()和Thread.join()。

    1)Object.wait()

    调用wait()方法前线程必须持有对象的锁。

    线程调用wait()方法时,会释放当前的锁,直到有其他线程调用notify()/notifyAll()方法唤醒等待锁的线程。

    需要注意的是,其他线程调用notify()方法只会唤醒单个等待锁的线程,如有有多个线程都在等待这个锁的话不一定会唤醒到之前调用wait()方法的线程。

    同样,调用notifyAll()方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。

    2)Thread.join()

    调用join()方法,会一直等待这个线程执行完毕(转换为 TERMINATED 状态)。

    2. TIMED_WAITING 与 RUNNABLE 状态转换

    TIMED_WAITING 与 WAITING 状态类似,只是 TIMED_WAITING 状态等待的时间是指定的。

    1)Thread.sleep(long)

    使当前线程睡眠指定时间。需要注意这里的“睡眠”只是暂时使线程停止执行,并不会释放锁。时间到后,线程会重新进入 RUNNABLE 状态。

    2)Object.wait(long)

    wait(long)方法使线程进入 TIMED_WAITING 状态。这里的wait(long)方法与无参方法 wait()相同的地方是,都可以通过其他线程调用notify()或notifyAll()方法来唤醒。

    不同的地方是,有参方法wait(long)就算其他线程不来唤醒它,经过指定时间 long 之后它会自动唤醒,拥有去争夺锁的资格。

    3)Thread.join(long)

    join(long)使当前线程执行指定时间,并且使线程进入 TIMED_WAITING 状态。

 

 

    参考链接:

    https://javabetter.cn/thread/thread-state-and-method.html 

posted @ 2024-05-10 10:39  欢乐豆123  阅读(10)  评论(0编辑  收藏  举报