Java多线程 (五)—— 线程的生命周期

文章目录

  • 前言
  • 1、线程生命周期
    • 1.1、NEW(新建)
    • 1.2、RUNNABLE(可运行)
    • 1.3、BLOCKED(阻塞)
    • 1.4、WAITING(等待)
    • 1.5、TIMED_WAITING(计时等待)
    • 1.5、TERMINATED(被终止)
  • 2、线程生命周期流程图

前言

看过大多数博客,认为生命周期有5个阶段的,也有6个阶段的。总结了几篇,细分的话,线程的生命周期包含了6个阶段:
1、NEW(新建):线程刚被创建,但是未被启动;
2、RUNNABLE(可运行):线程已经调用start()等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;
3、BLOCKED(阻塞):在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;
4、WAITING(等待):正在等待另一个线程执行特定的动作的线程处于这个状态。
5、TIMED_WAITING(计时等待):正在等待另一个线程执行动作达到指定等待时间的线程处于这个状态。
6、TERMINATED(被终止):已退出的线程处于此状态。

注意:Java中将操作系统中断休眠状态分为了三种状态,也就是:BLOCKED、WAITING、TIMED_WAITING。只要 Java 线程处于这三种状态之一,那么这个线程就永远没有 CPU 的使用权。


1、线程生命周期

1.1、NEW(新建)

举个例子:

public class ThreadTest extends Thread{
    @Override
    public void run() {
            
    }
}
//新建(new)一个线程
ThreadTest thread = new ThreadTest();

上面例子中new了一个线程对象。该线程就处于新建状态,还不能运行,此时JVM为其分配了内存,没有表现出任何线程的动态特征。

1.2、RUNNABLE(可运行)

可运行状态是个复合状态,可以再细分为两个状态:
(1)READY(就绪状态)
当线程对象调用了start()方法之后,该线程处于 就绪状态。处于就绪状态的线程位于线程队列中,此时它只是具备了运行的条件,能否获得CPU的使用权并开始运行,还需要等待系统的调度( 等待系统为其分配CPU时间片)。
(2)RUNNING(运行状态)
如果处于就绪状态的线程获得了CPU的使用权,并开始执行run()方法中的线程执行体,则该线程处于运行状态(即该线程从READY状态转变为RUNNING状态)。一个线程启动后,它可能不会一直处于运行状态,当运行状态的线程调用yield方法或使用完系统分配的时间后,系统就会剥夺该线程占用的CPU资源,让其他线程获得执行的机会(此时该线程又从RUNNING状态转变为READY状态)。需要注意的是,只有处于就绪状态的线程才可能转换到运行状态。

1.3、BLOCKED(阻塞)

阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
下面就列举一下线程由运行状态转换成阻塞状态的原因,以及如何从阻塞状态转换成就绪状态。
线程I/O:当线程调用了一个阻塞式的I/O方法时,该线程就会进入阻寒状态,如果想进入就绪状态就必须要等到这个阻塞的I/O方法返回。
线程同步锁(synchronized):当线程试图获取某个对象的同步锁时,如里该销被其他线程所持有,则当前线程会进入阻塞状态,如果想从阻塞状态进入就绪状态就必须获取到其他线程所持有的锁。

注意,线程从阻塞状态只能进入就绪状态,而不能直接进入运行状态,也就是说,结束阻塞的线程需要重新进入可运行池中,等待系统的调度。

1.4、WAITING(等待)

下面就列举一下线程由运行状态转换成等待状态的原因,以及如何从等待状状态转换成就绪状态。
线程等待:当线程调用了某个对象的wait()方法时,也会使线程进入等待状态,如果想进入就绪状态就需要使用notify()方法唤醒该线程。
线程加入:当在一个线程中调用了另一个线程的join()方法时,会使当前线程进入等待状态,在这种情况下,需要等到新加入的线程运行结束后才会结束等状态,进入就绪状态。

1.5、TIMED_WAITING(计时等待)

和WAITING 状态类似,区别在于状态的线程不会无限等待,如果在指定时间内完成了指定的操作,就会转换为 RUNNABLE状态。所以,在WATING方法中的大多数方法,只要加上一个时间参数,就会触发TIMED_WATING这个状态。具体如:Thread.currentThread().join(millis)、Thread.sleep(millis)、Obj.wait(timeout)等。

1.5、TERMINATED(被终止)

当线程顺利的完成run()方法中的任务,就会进入TERMINAL状态。同时,当线程抛出没有处理异常的时候,线程同样会变为TERMINAL状态。那如果业务上需要我们主动的终止线程,那应该怎么做呢?
可以通过调用线程的stop()、suspend()、resume()方法结束线程,但是这些方法早就已经被标记为过时方法,容易导致死锁,不推荐使用,推荐使用thread.interrupt();方来结束线程。

2、线程生命周期流程图

Java多线程 (五)—— 线程的生命周期_第1张图片

你可能感兴趣的:(java线程,java,jvm)