Java多线程核心方法详解:start、run、join与守护线程实战

Ivy
Ivy
发布时间:2026-10-16| 7人浏览过
原创

本文详解Java多线程开发中Thread类的核心方法,包括启动线程的start与run区别、控制执行的yield与sleep、协调关系的join、中断机制interrupt、守护线程daemon以及优先级priority,配合代码示例展示各方法在实际场景中的应用与注意事项。

启动线程的基础:start 与 run

在Java中,创建并启动线程最常见的误区是直接调用 run() 方法。理解 start() 和 run() 的本质区别是掌握多线程的第一步。

第1步:使用 start() 正式开启线程

目的:正确启动新线程,使线程进入可运行状态,由操作系统调度执行。

原理说明:

  • start() 是 synchronized 同步方法,确保线程只能被启动一次。如果多次调用会抛出 IllegalThreadStateException。
  • 它内部调用本地方法 start0()(底层C++实现),由JVM创建新的OS线程。
  • 线程启动后,会自动调用该线程对象的 run() 方法。
public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);
    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
        }
    }
}
private native void start0();

第2步:编写 run() 作为任务逻辑体

目的:定义线程实际需要执行的业务逻辑。

关键点:

  • run() 只是普通的方法覆盖,如果在主线程中直接调用 t.run(),代码将在当前线程顺序执行,不会开启新线程。
  • 只有当线程处于“新建”状态并通过 start() 触发时,JVM才会在新线程上下文中执行 run()。

线程控制与协调方法

第3步:yield() 主动让出CPU资源

作用:提示调度器当前线程愿意让出剩余的时间片,从“运行状态”退回到“就绪状态”,等待重新调度。

特点:

  • 是静态方法,仅对同优先级或更高优先级的线程有效。
  • 如果系统中没有其他同级或更高级别的线程准备运行,当前线程可能继续执行。
  • 不具有强制性,具体让给谁由系统决定,不建议用于关键逻辑控制。
public static native void yield();

第4步:join() 实现线程合并(串行化)

作用:在当前线程中调用另一个线程的 join() 方法,将导致当前线程暂停,直到目标线程执行完毕。

应用场景:需要等待子线程完成某些预处理才能进行后续业务,即“线程插队”。它将并行逻辑强制转为串行。

public class ThreadMethod02 {
    public static void main(String[] args) throws InterruptedException {
        T2 t2 = new T2();
        t2.start();
        //主线程打印
        int count = 0;
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(1000);
            System.out.println("main" + i);
            if (++count == 5) {
                t2.join();//主线程在此处阻塞,等待t2执行完
            }
        }
    }
}
class T2 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            try {
                Thread.sleep(1000); 
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("A" + i);
        }
    }
}

第5步:sleep() 暂停当前线程

作用:使当前正在执行的线程进入“阻塞状态”指定的时间,期间让出CPU使用权但不释放锁。

  • sleep(long millis):毫秒级休眠。
  • sleep(long millis, int nanos):纳秒级高精度休眠。

注意:睡眠可以被其他线程通过 interrupt() 打断,此时会抛出 InterruptedException。

线程中断与生命周期管理

第6步:interrupt() 发送中断信号

作用:标记线程为“中断状态”,并非强制杀死线程。

机制:

  • 如果目标线程正处于阻塞状态(如调用了 sleep, wait, join),调用 interrupt() 会立即清除中断标志并抛出 InterruptedException,线程需捕获异常处理退出逻辑。
  • 如果目标线程处于运行状态,中断标志会被设置为true,线程继续执行,直到下一次调用阻塞方法时检测标志并做出反应。
public class ThreadMethod03 {
    public static void main(String[] args) throws InterruptedException {
        T3 t3 = new T3();
        t3.start();
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName());
        }
        t3.interrupt();//向子线程发送中断信号
    }
}
class T3 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("A");
        }
        try {
            System.out.println("进行休眠");
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "被Interrupted!!!");
            // 通常在此处处理清理工作或退出循环
        }
    }
}

第7步:daemon 守护线程设置

定义:Java线程分用户线程(User Thread)和守护线程(Daemon Thread)。守护线程用于服务后台任务(如垃圾回收),当所有用户线程结束时,JVM会自动退出,无论守护线程是否在运行。

操作方法:

  • setDaemon(true):必须在 start() 之前调用,否则抛出 IllegalThreadStateException。
  • isDaemon():判断当前是否为守护线程。
public class ThreadMethod04 {
    public static void main(String[] args) throws InterruptedException {
        T4 t4 = new T4();
        t4.setDaemon(true);//必须在start前设置
        t4.start();
        if (t4.isDaemon()) {
            System.out.println("子线程是守护线程");
        }
        //主线程执行5秒后结束,子线程随之终止
        for (int i = 1; i <= 5; i++) {
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}
class T4 extends Thread {
    @Override
    public void run() {
        while (true) { //无限循环
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
}

结果现象:当主线程(用户线程)结束后,JVM进程退出,T4守护线程即使未执行完毕也会立即停止。

第8步:Priority 线程优先级管理

范围:最小值1 (MIN_PRIORITY),默认5 (NORM_PRIORITY),最大值10 (MAX_PRIORITY)。

特性:

  • 优先级仅影响线程调度概率,不保证高优先级一定先于低优先级执行,最终取决于操作系统调度算法。
  • 跨平台风险:不同OS支持的优先级数量不同,过度依赖优先级可能导致移植性问题。
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
public class ThreadMethod05 {
    public static void main(String[] args) {
        T5 t5 = new T5();
        t5.setPriority(10);
        int priority = t5.getPriority();
        System.out.println(priority); // 输出 10
    }
}
class T5 extends Thread {
    @Override
    public void run() {
        System.out.println("High Priority Thread Running");
    }
}

总结

掌握Java多线程的核心在于理解线程状态的流转与各方法的副作用。start负责创建新线程,run承载逻辑;sleep和yieid用于让步,但前者释放CPU而后者可能重入;join用于线程间同步等待;interrupt是实现优雅退出的关键信号;daemon则适用于无感知的后台服务。合理组合这些方法,才能编写出健壮的多线程应用。以上就是Java多线程方法详细内容的资料,更多关于Java并发编程的技术指南请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。