面试系列之-线程的生命周期(JAVA基础)

2023-08-21 20:19:47 浏览数 (1)

线程生命状态说明

Thread.State是一个内部枚举类,定义了6个枚举常量,分别代表Java线程的6种状态:

代码语言:javascript复制
public static enum State {    NEW, //新建    RUNNABLE, //可执行:包含操作系统的就绪、运行两种状态    BLOCKED, //阻塞    WAITING, //等待    TIMED_WAITING, //限时等待    TERMINATED; //终止}

NEW状态:创建成功但是没有调用start()方法启动的Thread线程实例都处于NEW状态。

TIMED_WAITING状态:线程处于一种特殊的等待状态,准确地说,线程处于限时等待状态

(1)Thread.sleep(int n):使得当前线程进入限时等待状态,等待时间为n毫秒。

(2)Object.wait():带时限的抢占对象的monitor锁。

(3)Thread.join():带时限的线程合并。

(4)LockSupport.parkNanos():让线程等待,时间以纳秒为单位。

(5)LockSupport.parkUntil():让线程等待,时间可以灵活设置。

Thread.yield()方法作用是:暂停当前正在执行的线程对象(及放弃当前拥有的cup资源), 并执行其他线程。yield()做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其 他线程获得运行机会。因此使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

NEW:毫无疑问表示的是刚创建的线程,还没有开始启动。

RUNNABLE: 表示线程已经触发start()方式调用,线程正式启动,线程处于运行中状态。

BLOCKED:表示线程阻塞,等待获取锁,如碰到synchronized、lock等关键字等占用临界区的情况,一旦获取到锁就进行RUNNABLE状态继续运行。

WAITING:表示线程处于无限制等待状态,等待一个特殊的事件来重新唤醒,如通过wait()方法进行等待的线程等待一个notify()或者notifyAll()方法,通过join()方法进行等待的线程等待目标线程运行结束而唤醒,一旦通过相关事件唤醒线程,线程就进入了RUNNABLE状态继续运行。

TIMED_WAITING:表示线程进入了一个有时限的等待,如sleep(3000),等待3秒后线程重新进行RUNNABLE状态继续运行。

TERMINATED:表示线程执行完毕后,进行终止状态。

需要注意的是,一旦线程通过start方法启动后就再也不能回到初始NEW状态,线程终止后也不能再回到RUNNABLE状态。

线程状态切换详细说明

NEW状态

通过new Thread(…)已经创建线程,但尚未调用start()启动线程,该线程处于NEW(新建)状态。虽然前面介绍了4种方式创建线程,但是其中的其他三种方式本质上都是通过new Thread()创建线程,仅仅是创建了不同的target执行目标实例(如Runnable实例)。

RUNNABLE状态

Java把Ready(就绪)和Running(执行)两种状态合并为一种状态:RUNNABLE(可执行)状态(或者可运行状态)。调用了线程的start()实例方法后,线程就处于就绪状态。此线程获取到CPU时间片后,开始执行run()方法中的业务代码,线程处于执行状态。

就绪状态

就绪状态仅仅表示线程具备运行资格,如果没有被操作系统的调度程序挑选中,线程就永远处于就绪状态。当前线程进入就绪状态的条件大致包括以下几种:

·调用线程的start()方法,此线程就会进入就绪状态。

·当前线程的执行时间片用完。

·线程睡眠(Sleep)操作结束。

·对其他线程合入(Join)操作结束。

·等待用户输入结束。

·线程争抢到对象锁(Object Monitor)。

·当前线程调用了yield()方法出让CPU执行权限。

执行状态

线程调度程序从就绪状态的线程中选择一个线程,被选中的线程状态将变成执行状态。这也是线程进入执行状态的唯一方式。

BLOCKED状态

处于BLOCKED(阻塞)状态的线程并不会占用CPU资源,以下情况会让线程进入阻塞状态:

(1)线程等待获取锁

等待获取一个锁,而该锁被其他线程持有,则该线程进入阻塞状态。当其他线程释放了该锁,并且线程调度器允许该线程持有该锁时,该线程退出阻塞状态。

(2)IO阻塞

线程发起了一个阻塞式IO操作后,如果不具备IO操作的条件,线程就会进入阻塞状态。IO包括磁盘IO、网络IO等。IO阻塞的一个简单例子:线程等待用户输入内容后继续执行。

WAITING状态

处于WAITING(无限期等待)状态的线程不会被分配CPU时间片,需要被其他线程显式地唤醒,才会进入就绪状态。线程调用以下3种方法会让自己进入无限等待状态:

·Object.wait()方法,对应的唤醒方式为:

·Object.notify()/Object.notifyAll()。

·Thread.join()方法,对应的唤醒方式为:被合入的线程执行完毕。

·LockSupport.park()方法,对应的唤醒方式为:

·LockSupport.unpark(Thread)。

TIMED_WAITING状态

处于TIMED_WAITING(限时等待)状态的线程不会被分配CPU时间片,如果指定时间之内没有被唤醒,限时等待的线程会被系统自动唤醒,进入就绪状态。以下3种方法会让线程进入限时等待状态:

·Thread.sleep(time)方法,对应的唤醒方式为:sleep睡眠时间结束。

·Object.wait(time)方法,对应的唤醒方式为:调用

·Object.notify()/Object.notifyAll()主动唤醒,或者限时结束。

·LockSupport.parkNanos(time)/parkUntil(time)方法,对应的唤醒方式

为:线程调用配套的LockSupport.unpark(Thread)方法结束,或者线程停止(park)时限结束。

进入BLOCKED状态、WAITING状态、TIMED_WAITING状态的线程都会让出CPU的使用权;另外,等待或者阻塞状态的线程被唤醒后,进入Ready状态,需要重新获取时间片才能接着运行。

TERMINATED状态

线程结束任务之后,将会正常进入TERMINATED(死亡)状态;或者说在线程执行过程中发生了异常(而没有被处理),也会导致线程进入死亡状态。

0 人点赞