你好,我是吴计可师,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。
文章可能会比较长,主要解析的非常详解,或涉及一些底层知识,供面试高阶难度用。可以根据自己实际理解情况合理取舍阅读
Java 中的线程有 7 种状态,这些状态在 Thread 类中通过 Thread.State 枚举定义。这些状态描述了线程的生命周期中的不同阶段。下面详细介绍这些线程状态:
线程被创建出来,但尚未开始执行。此时线程处于新建状态。
当线程对象被创建时,但 start() 方法还没有被调用。
0
线程已经启动,正在等待 CPU 的时间片来执行。线程处于 可运行状态,但并不意味着线程正在执行,它可能正在等待 CPU 的调度。
何时进入此状态:当调用 start() 方法后,线程从 新建状态 进入 可运行状态。在操作系统中,线程已经准备好可以执行,调度器会决定什么时候实际执行它。
注意:在 Java 中,线程一旦进入了 可运行状态,并不意味着它会马上开始执行。它可能会等待 CPU 时间片,直到调度器给它分配 CPU 时间。
线程因为等待获取锁(如同步锁)而进入 阻塞状态。当一个线程试图进入同步代码块时,如果该代码块的锁已经被其他线程占用,线程会进入 阻塞状态,直到它能够获得该锁。
何时进入此状态:当线程调用 synchronized 关键字修饰的方法或块,并且该线程无法获取锁时,它会进入 阻塞状态。
线程进入 等待状态,意味着它在等待其他线程的通知来继续执行。常见的场景包括线程调用了 Object.wait()、Thread.join() 或 Lock.await() 等方法,导致线程进入此状态。
何时进入此状态:
调用 Object.wait() 方法时。
调用 Thread.join() 方法时(等待其他线程完成)。
调用 Lock.await() 方法时(例如,使用 ReentrantLock)。
何时退出此状态:当其他线程调用了相应的通知方法(如 notify()、notifyAll())或超时到达时,线程才会从 等待状态 退出。
线程处于 限时等待状态,即它在等待一段指定时间后自动恢复运行,或者等待某个条件完成后继续执行。常见的场景包括调用 Thread.sleep()、Object.wait(long millis)、Thread.join(long millis) 或 Lock.lock(long millis) 等方法。
何时进入此状态:当调用下面的方法时,线程会进入 限时等待状态:
Thread.sleep(milliseconds)
Object.wait(milliseconds)
Thread.join(milliseconds)
Lock.lock(long timeout, TimeUnit unit)
何时退出此状态:当超时或其他条件触发时,线程会从 限时等待状态 退出。
线程已经完成其任务,或由于异常、错误等原因被终止。此时,线程的生命周期结束,线程处于 终止状态。
何时进入此状态:线程在完成 run() 方法的执行或者因未捕获异常而停止时会进入 终止状态。
线程被中断时,它会进入 中断状态。中断是线程管理中的一种机制,线程可以被请求中断。调用 Thread.interrupt() 可以中断一个线程,线程会根据中断的方式进行相应的处理。并不是所有线程都会立即停止,线程需要在适当的位置检查中断标志并处理它。
如果线程正在执行可中断的操作(如 sleep()、wait() 等),中断会导致这些方法抛出 InterruptedException,线程进入 中断状态,并且可以通过 Thread.interrupted() 来检查是否有中断请求。
注意:中断线程并不会立刻停止它,线程仍然需要检查中断标志并决定如何处理。
整体状态图示
8.1 Thread.sleep() 和 Object.wait() 会导致线程进入哪种状态?
Thread.sleep(long millis):让线程进入 Timed Waiting(限时等待状态),等待指定的时间后,线程会恢复运行。Object.wait():让线程进入 Waiting(等待状态),直到被其他线程调用 notify() 或 notifyAll() 方法唤醒。
当一个线程调用 join() 方法时,它会使当前线程等待,直到被调用的线程执行完毕。因此,当前线程会进入 Waiting(等待状态),直到目标线程完成。
当一个线程调用 notify() 或 notifyAll() 方法时,它会唤醒一个或多个处于 Waiting(等待状态) 的线程。被唤醒的线程将会重新进入 Runnable(可运行状态),等待操作系统的线程调度器分配 CPU 时间片执行。
线程进入 Waiting(等待状态) 后,只有在以下几种情况时才会退出该状态:
被其他线程调用 notify() 或 notifyAll() 唤醒,恢复为 Runnable(可运行状态)。
被中断(即调用 interrupt()),如果线程在等待时被中断,通常会抛出 InterruptedException 异常,并进入中断状态。
Thread.sleep():使当前线程进入 Timed Waiting(限时等待状态),在指定时间后恢复执行,不会释放锁。
Object.wait():使当前线程进入 Waiting(等待状态),直到被其他线程调用 notify() 或 notifyAll() 唤醒。调用 wait() 时,会释放持有的锁。
可以通过调用另一个线程的 join() 方法来实现线程同步。调用 join() 的线程会进入 Waiting(等待状态),直到被调用的线程执行完毕。
Thread t1 = new Thread(() -> {
System.out.println("Thread 1");
});
Thread t2 = new Thread(() -> {
try {
t1.join(); // 等待 t1 执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2");
});
t1.start();
t2.start();
今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!