当前位置: 首页 > article >正文

Java基础夯实——2.4 线程的生命周期

在这里插入图片描述

Java线程生命周期

Java线程的生命周期分为:新建(New)就绪(Runnable)阻塞(Blocked)等待 (Waiting)计时等待(Timed_Waiting)终止(Terminated) 六种状态,这些状态通过Thread.State枚举类定义。

1. 新建状态(New)

  • 当一个线程对象被创建但尚未调用start()方法时,线程处于新建状态

  • 在这个阶段,线程对象仅存在于内存中,但尚未与操作系统的底层线程关联。

  • 可以为线程设置名称、优先级等属性,但线程未开始执行。

  • 状态特点

    • 调用start()方法后会转移到就绪状态
    • 如果没有调用start()方法就试图调用join()interrupt(),将抛出异常。
  • 示例

public class ThreadLifecycleExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("Thread is running."));
        // 线程处于新建状态
        System.out.println("Thread State: " + thread.getState()); // 输出 NEW
    }
}

2. 就绪状态(Runnable)

  • 调用start()方法后,线程进入就绪状态

  • 此时线程已交给操作系统线程调度器管理,但未必立即运行。

  • 线程调度器根据算法(如时间片轮转)决定何时将线程分配到CPU。

  • 状态特点

    • 此状态不等同于“运行中”,线程可能随时等待被调度。
    • 调用start()后,无法再次调用该方法,否则会抛出IllegalThreadStateException
  • 示例

public class ThreadLifecycleExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread is running.");
        });
        thread.start();
        System.out.println("Thread State after start(): " + thread.getState()); // 输出 RUNNABLE
    }
}

3. 运行状态(Running)

  • 当线程获得CPU时间片后,线程进入运行状态

  • 此时线程执行其run()方法中的任务。

  • 线程调度器可能在运行状态下暂停线程,并将其转移回就绪状态以让其他线程运行。

  • 状态特点

    • 开发者无法显式设置线程为运行状态,状态完全由操作系统调度决定。
    • 多线程环境下,运行状态的线程可能随时被挂起。
  • 代码示例

public class ThreadLifecycleExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread State: " + Thread.currentThread().getState()); // 输出 RUNNABLE 或运行中
        });
        thread.start();
    }
}

4. 等待/阻塞/计时等待状态

线程可能因资源或时间限制无法继续运行时,会进入以下三种状态:

(1)等待状态(Waiting)

  • 线程无限期地等待另一个线程唤醒它。

  • 通常是通过Object.wait()Thread.join()进入。

  • 唤醒方式包括调用notify()notifyAll()

  • 状态特点

    • 无法自行恢复,必须由另一个线程显式唤醒。
    • 常用于线程间协作。
  • 示例

public class WaitingExample {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is waiting.");
                    lock.wait(); // 线程进入等待状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread resumed.");
            }
        });

        thread.start();
        Thread.sleep(1000); // 主线程暂停1秒
        synchronized (lock) {
            lock.notify(); // 唤醒等待线程
        }
    }
}

(2)计时等待状态(Timed Waiting)

  • 线程等待一段时间后会自动唤醒。

  • 调用如Thread.sleep()join(timeout)wait(timeout)方法会进入该状态。

  • 状态特点

    • 无需显式唤醒,时间结束后线程自动进入就绪状态
    • 常用于延时操作。
  • 示例

public class TimedWaitingExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread is sleeping.");
                Thread.sleep(2000); // 线程进入计时等待状态
                System.out.println("Thread woke up.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        thread.start();
    }
}

(3)阻塞状态(Blocked)

  • 当一个线程试图进入被其他线程持有的同步代码块时,会进入阻塞状态。

  • 一旦锁被释放,线程将进入就绪状态等待调度。

  • 状态特点

    • 阻塞是由于线程竞争共享资源而导致的。
    • 常见于synchronized关键字或锁机制。
  • 示例

public class BlockedExample {
    public static void main(String[] args) {
        Object lock = new Object();

        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(5000); // 保持锁5秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 2 acquired the lock.");
            }
        });

        thread1.start();
        thread2.start();
    }
}

5. 终止状态(Terminated)

  • 描述

    • 当线程执行完成或因异常退出时,进入终止状态
    • 终止后的线程无法再次启动。
  • 状态特点

    • 使用isAlive()方法可以检查线程是否仍存活。
    • 线程终止后,它的资源会被JVM回收。
  • 代码示例

public class TerminatedExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("Thread is running."));
        thread.start();

        try {
            thread.join(); // 等待线程终止
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Thread State: " + thread.getState()); // 输出 TERMINATED
    }
}

常见问题

1. 线程的生命周期包括哪几个阶段?**

New : 为线程分配内存并初始化其成员变量值
Runnable:JVM完成方法调用栈和程序计数器创建,等待线程调用和运行
Blocked:主动或被动放弃CPU使用权并暂停运行
Waiting:等待
Timed_Waiting:超时后会被自动唤醒
Terminated:正常或者异常结束或者手动结束

2. 在哪些情况下会出现线程阻塞?

线程阻塞(Blocked)通常发生在以下几种场景中:

  1. 等待锁:
    • 一个线程试图进入由synchronized关键字保护的代码块或方法,但锁已被其他线程持有,当前线程将进入阻塞状态。
    • 示例:
      synchronized (lock) {
          // 当前线程执行时,其他线程试图进入会阻塞
      }
      
  2. I/O操作:
    • 线程等待输入/输出完成时,如从文件或网络读取数据。
  3. 线程阻塞工具类:
    • 使用Lock或类似机制时,线程可能因为未能获取锁而被阻塞。
    • 示例:
      Lock lock = new ReentrantLock();
      lock.lock(); // 其他线程会在这里阻塞
      
  4. 其他同步机制:
    • 使用CountDownLatchSemaphore等并发工具,线程可能会因未满足条件而阻塞。

3. 线程在就绪状态下会立即执行吗?

不会 线程处于就绪状态时,已经准备好运行,但是否执行取决于线程调度器的安排。
线程调度器根据操作系统的调度策略(如时间片轮转或优先级)决定何时将线程分配到CPU。
如果有多个线程处于就绪状态,它们需要等待调度。

4. 什么是线程阻塞?

**线程阻塞(Blocked)**是指线程因为某种原因被挂起,无法继续执行,直到某些条件满足为止。

  • 触发原因:
    1. 等待锁: 线程试图进入被其他线程持有的synchronized代码块或方法。
    2. 资源不可用: 线程等待特定资源(如文件、网络数据)。
    3. 线程竞争: 线程因并发控制工具(如锁、信号量)而受阻。

http://www.kler.cn/a/401387.html

相关文章:

  • 散户持股增厚工具:智能T0算法交易
  • web应用安全和信息泄露预防
  • 网络传输:网卡、IP、网关、子网掩码、MAC、ARP、路由器、NAT、交换机
  • 数据分析24.11.13
  • QList和QSet常用操作(查找、插入、排序、交集)
  • 使用Python编写一个简单的网页爬虫,从网站抓取标题和内容。
  • FastDDS之DataSharing
  • Odoo中,要实现实时数据推送,SSE 与 WebSocket 该如何选择
  • 利用python 检测当前目录下的所有PDF 并转化为png 格式
  • 无人机侦察打击方案(1)
  • React渲染和更新机制及其核心内容详解
  • ChatGPT-o1快速完成论文选题的9类提示词
  • ggplot2-scale_x_continuous()
  • 【面试】前端vue项目架构详细描述
  • 一文详解架构分层
  • Photoshop(PS)——人像磨皮
  • 并发专题(1)之深入理解并发、线程与等待通知机制
  • 24. 两两交换链表中的节点
  • 行列式的理解与计算:线性代数中的核心概念
  • 浅谈python
  • AI新闻周刊 | 最新AI资讯速递(11.11-11.17)
  • SMARTFORMS函数调用完整示例:打印工厂物料信息
  • 建造者模式(Builder Pattern)
  • 数字后端零基础入门系列 | Innovus零基础LAB学习Day11(Function ECO流程)
  • [控制理论]—位置式PID与增量式PID
  • 【大数据学习 | Spark】RDD的概念与Spark任务的执行流程