Java Thread 类核心技术笔记

一、概述

Java 中的 java.lang.Thread 类是线程实现的核心基础,它封装了线程的所有核心属性和行为,允许我们在 Java 程序中创建和管理多线程执行流程。Java 虚拟机(JVM)支持多线程并发执行,每个 Thread 实例对应一个独立的执行线程,线程的执行逻辑封装在 run() 方法中,且不能直接调用 run() 方法启动线程(直接调用仅相当于普通方法调用,不会创建新线程),必须通过 start() 方法触发 JVM 对线程的调度。

二、核心重要非方法内容

1. 线程的两种创建方式

Thread 类本身实现了 Runnable 接口,创建线程有两种标准方式,本质都是封装执行逻辑 run() 方法:

  • 方式一:继承 Thread 类,重写 run() 方法
    优点:实现简单,可直接通过 this 访问当前线程的属性和方法;
    缺点:Java 单继承限制,子类无法再继承其他类,耦合度较高。
  • 方式二:实现 Runnable 接口,将实例传入 Thread 构造器
    优点:规避单继承限制,解耦执行逻辑和线程管理,便于线程池复用任务逻辑;
    缺点:无法直接访问线程属性,需通过 Thread.currentThread() 获取当前线程实例。

2. 线程的优先级

Thread 类定义了 3 个优先级常量,用于提示 JVM 调度线程的优先级(仅为提示,不保证严格按照优先级执行,具体依赖操作系统和 JVM 实现):

  • MIN_PRIORITY = 1:最低优先级
  • NORM_PRIORITY = 5:默认优先级(新创建的线程继承父线程的优先级,主线程默认是 5)
  • MAX_PRIORITY = 10:最高优先级

注意:线程优先级不能超出 1-10 的范围,否则会抛出 IllegalArgumentException,且线程组会限制线程的最大优先级,设置的优先级不能超过线程组的最大优先级。

3. 守护线程(Daemon Thread)

线程分为用户线程守护线程

  • 用户线程:默认创建的线程(非守护线程),JVM 会等待所有用户线程执行完毕后才会退出;
  • 守护线程:为用户线程提供辅助服务(如垃圾回收线程 GC、定时器后台线程),当所有用户线程执行完毕,JVM 会直接退出,不会等待守护线程执行完成。

关键特性:setDaemon(boolean on) 方法必须在线程启动(start())前调用,否则会抛出 IllegalThreadStateException

4. 线程的 6 种状态(State 枚举)

Thread 类通过 State 枚举定义了线程的生命周期,一个线程在任意时刻只能处于一种状态,状态转换由 JVM 控制,无法手动干预:

  • NEW:新建状态,线程对象已创建,但尚未调用 start() 方法,未进入 JVM 线程调度队列;
  • RUNNABLE:可运行状态,包含「就绪」和「运行中」两种子状态,线程已启动,等待操作系统分配 CPU 资源(就绪)或正在执行 run() 方法(运行中);
  • BLOCKED:阻塞状态,线程等待获取监视器锁(synchronized 锁),无法执行;
  • WAITING:无限等待状态,线程无超时等待其他线程执行特定操作(如 Object.wait()Thread.join() 无参版),需被其他线程唤醒才能进入就绪状态;
  • TIMED_WAITING:定时等待状态,线程带超时时间等待(如 Thread.sleep(long)Object.wait(long)),超时时间到会自动唤醒进入就绪状态;
  • TERMINATED:终止状态,线程的 run() 方法执行完毕或因未捕获异常终止,生命周期结束。

三、常用核心方法(精选 7 种)

1. void start() - 启动线程

  • 核心作用:触发 JVM 创建新线程,将线程状态从 NEW 转换为 RUNNABLE,等待 CPU 调度执行,线程启动后会自动调用 run() 方法
  • 注意事项:一个线程只能调用一次 start() 方法,重复调用会抛出 IllegalThreadStateException

2. void run() - 线程执行逻辑封装

  • 核心作用:封装线程的核心执行逻辑,JVM 调度线程后会自动调用该方法,无需手动调用;
  • 注意事项:
    • 直接调用 run() 方法不会创建新线程,仅相当于在当前线程中执行一个普通方法;
    • 若创建 Thread 时传入了 Runnable 实例,run() 方法会调用 Runnable 实例的 run() 方法,否则 run() 方法为空,无任何执行逻辑。

3. static Thread currentThread() - 获取当前执行线程

  • 核心作用:静态方法,返回当前正在执行该方法的线程实例,可用于获取线程的名称、优先级、状态等属性;
  • 典型场景:在 Runnable 实现类中获取当前线程(无 this 引用),或在多线程环境中打印当前执行线程标识。

示例:

public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        // 获取当前执行的线程
        Thread current = Thread.currentThread();
        System.out.println("当前线程名称:" + current.getName());
    }, "测试线程");
    thread.start();
}

4. static void sleep(long millis) - 线程休眠

  • 核心作用:静态方法,让当前执行线程进入 TIMED_WAITING 状态,休眠指定的毫秒数(millis),休眠期间不会释放已持有的监视器锁(synchronized 锁);
  • 注意事项:
    • 会抛出 InterruptedException 受检异常,需捕获或声明抛出(休眠期间线程若被中断,会触发该异常并清除中断状态);
    • 休眠时间受操作系统定时器精度影响,并非绝对准确,休眠结束后线程进入 RUNNABLE 状态,等待 CPU 调度;
    • 重载方法 sleep(long millis, int nanos) 支持纳秒级休眠,本质是对毫秒数的补充,最终仍转换为毫秒级休眠。

5. void interrupt() - 中断线程

  • 核心作用:向目标线程发送中断请求,不会强制终止线程,仅设置线程的中断标志位为 true
  • 中断的处理逻辑:
    • 若线程处于 sleep()wait()join() 等阻塞状态,会抛出 InterruptedException,并清除中断标志位(标志位变为 false);
    • 若线程处于正常运行状态,仅设置中断标志位,需由线程自身通过 isInterrupted()interrupted() 检测中断标志位,自行决定是否终止执行(优雅中断);
  • 典型场景:实现优雅的线程退出,替代已废弃的 stop() 方法(stop() 会强制终止线程,可能导致资源泄露、数据不一致)。

6. boolean isInterrupted() - 检测线程中断状态

  • 核心作用:实例方法,返回目标线程的中断标志位状态,不会清除中断标志位
  • 对比:静态方法 interrupted() 也可检测中断状态,但会清除中断标志位(调用后标志位变为 false),且仅能检测当前执行线程的中断状态。

7. void join() - 线程等待

  • 核心作用:实例方法,让当前执行线程等待目标线程执行完毕(进入 WAITING 状态),再继续执行当前线程的后续逻辑;
  • 注意事项:
    • 重载方法 join(long millis)join(long millis, int nanos) 支持超时等待,超时后当前线程不再等待,进入 RUNNABLE 状态;
    • 会抛出 InterruptedException 受检异常,等待期间当前线程若被中断,会触发该异常;
    • 等待期间不会释放当前线程已持有的监视器锁。

示例:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程执行:" + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    thread.start();
    // 主线程等待子线程执行完毕后,再执行后续逻辑
    thread.join();
    System.out.println("主线程执行完毕");
}

四、补充:已废弃的危险方法

Thread 类中的 stop()suspend()resume() 方法已被废弃,存在严重安全隐患,禁止在开发中使用:

  1. stop():强制终止线程,会释放线程所有持有的锁,可能导致共享数据处于不一致状态;
  2. suspend():暂停线程,且不会释放持有的锁,容易导致死锁(其他线程无法获取该锁,而 resume() 若在获取锁前调用,会导致线程永久暂停);
  3. resume():恢复被 suspend() 暂停的线程,与 suspend() 配套使用,存在死锁风险。

五、总结

  1. Thread 类是 Java 多线程的基础,线程启动依赖 start() 方法,执行逻辑封装在 run() 方法中,有继承 Thread 和实现 Runnable 两种创建方式;
  2. 线程有 6 种生命周期状态,由 JVM 自动转换,核心状态转换包括「新建→可运行→终止」「可运行→阻塞/等待→可运行」;
  3. 常用核心方法聚焦于线程启动(start())、休眠(sleep())、中断(interrupt())、等待(join())和状态检测(currentThread()isInterrupted()),且需避免使用已废弃的危险方法;
  4. 守护线程为用户线程提供辅助,JVM 退出不等待守护线程,优先级仅为 JVM 调度提示,不保证严格执行。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐