从零开始学多线程:Thread 类 5 大常用方法全解析!

《Java零基础教学》是一套深入浅出的 Java 编程入门教程。全套教程从Java基础语法开始,适合初学者快速入门,同时也从实例的角度进行了深入浅出的讲解,让初学者能够更好地理解Java编程思想和应用。

本教程内容包括数据类型与运算、流程控制、数组、函数、面向对象基础、字符串、集合、异常处理、IO 流及多线程等 Java 编程基础知识,并提供丰富的实例和练习,帮助读者巩固所学知识。本教程不仅适合初学者学习,也适合已经掌握一定 Java 基础的读者进行查漏补缺。

前言

大家好!我是不熬夜崽崽。众所周知,在程序开发中,几乎所有的程序都不可避免地涉及到多线程。线程的引入使得程序能够并发执行多个任务,从而提升程序的性能和响应速度。对于大多数开发者来说,Thread 类无疑是最常用的多线程工具之一。然而,虽然 Thread 类的功能强大,但其中的一些方法如何使用,常常让人摸不着头脑。

今天,我们就来深入探讨 Thread 类中五个最常用的方法:start()run()sleep()join()interrupt()。这些方法是多线程开发中的核心,它们的正确使用可以让我们更高效地控制线程的生命周期和执行顺序。

摘要

Thread 类是 Java 中用于创建和管理线程的核心类。多线程编程的关键在于如何合理控制线程的执行顺序、状态转换以及如何进行线程间的协作。本文将详细介绍 Thread 类的五个常用方法,分别是:start()run()sleep()join()interrupt(),并通过实例讲解它们在实际开发中的应用和注意事项。希望通过这篇文章,大家能够更深入地理解多线程的实现原理和实际应用。

简介

在 Java 中,Thread 类是用来表示一个线程的对象。每个 Thread 对象都对应一个执行的线程,通过调用 start() 方法启动线程。线程的执行通常由 run() 方法控制,而线程的暂停、等待、终止等控制,则可以通过 sleep()join()interrupt() 来实现。合理地使用这些方法,能够让我们更加高效地进行多线程开发。

概述

1. start()

start() 方法是启动线程的关键方法。当我们创建一个线程时,调用 start() 方法会让线程进入就绪状态,从而开始执行线程中的 run() 方法。如果直接调用 run() 方法而不是 start(),那么代码就会像普通方法一样按顺序执行,而不会开启新线程。因此,start() 是启动线程的正确方式。

2. run()

run() 方法是线程执行的入口方法。这个方法在 Thread 对象调用 start() 后会自动被执行。通常,我们会在 run() 方法中编写线程需要执行的代码。注意,我们不应该直接调用 run() 方法,而是通过 start() 方法间接启动 run()

3. sleep()

sleep() 方法使当前线程暂停执行一定的时间。它是静态方法,调用时可以指定一个时间参数,单位是毫秒。使用 sleep() 可以控制线程的执行节奏,但需要注意,sleep() 会让线程进入阻塞状态,不会释放锁,因此会影响到程序的执行效率和响应性。

4. join()

join() 方法用于让当前线程等待目标线程执行完成后再继续执行。通常,我们会在主线程中调用某个子线程的 join() 方法,这样主线程会等到子线程完成后再继续执行。这对于线程间的顺序控制非常有用。

5. interrupt()

interrupt() 方法用于中断一个线程的执行。当线程处于阻塞状态(如等待、睡眠或其他等待方法),调用 interrupt() 会让线程抛出 InterruptedException 异常,并返回到就绪状态。需要注意的是,interrupt() 只能中断处于阻塞状态的线程,对正在运行的线程没有影响。

核心源码解读

1. start()

java 复制代码
Thread thread = new Thread(() -> System.out.println("Thread started"));
thread.start();  // 启动线程

start() 方法会让当前线程进入就绪状态,等待 CPU 调度执行。如果不调用 start(),线程就不会启动。

2. run()

java 复制代码
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Running in a separate thread");
    }
}

run() 方法中包含了线程需要执行的任务。每当调用 start() 方法时,run() 会自动被执行。

3. sleep()

java 复制代码
Thread.sleep(1000);  // 当前线程休眠 1 秒

sleep() 让当前线程暂停指定的时间,单位是毫秒。这里的 1000 毫秒意味着线程会暂停 1 秒。

4. join()

java 复制代码
Thread thread = new Thread(() -> System.out.println("Child thread"));
thread.start();
thread.join();  // 主线程等待子线程执行完再继续
System.out.println("Main thread");

join() 方法让主线程等待子线程执行完毕后再继续执行,这对于线程顺序控制非常有用。

5. interrupt()

java 复制代码
Thread thread = new Thread(() -> {
    try {
        Thread.sleep(5000);  // 休眠 5 秒
    } catch (InterruptedException e) {
        System.out.println("Thread interrupted");
    }
});
thread.start();
thread.interrupt();  // 中断线程

interrupt() 方法会中断线程的执行。如果线程正在执行 sleep() 或其他阻塞操作时,它会抛出 InterruptedException 异常。

案例分析

假设我们需要编写一个多线程任务,其中主线程启动两个子线程并让主线程等待子线程执行完再继续。我们可以通过 start()join() 方法来实现。

示例代码

接着,我给大家展示下,结合理论与实战给大家把知识点讲透,案例代码如下:

java 复制代码
/**
 * @Author wf
 * @Date 2025-04-13 21:12
 */
public class ThreadExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            try {
                Thread.sleep(1000);  // 模拟任务执行
                System.out.println("Thread 1 completed");
            } catch (InterruptedException e) {
                System.out.println("Thread 1 interrupted");
            }
        });

        Thread thread2 = new Thread(() -> {
            try {
                Thread.sleep(1500);  // 模拟任务执行
                System.out.println("Thread 2 completed");
            } catch (InterruptedException e) {
                System.out.println("Thread 2 interrupted");
            }
        });

        thread1.start();  // 启动线程 1
        thread2.start();  // 启动线程 2

        try {
            thread1.join();  // 主线程等待线程 1 完成
            thread2.join();  // 主线程等待线程 2 完成
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("All threads completed");
    }
}

输出预期结果

根据如上所给代码案例,预期输出结果如下:

json 复制代码
Thread 1 completed
Thread 2 completed
All threads completed

结果运行展示

根据如上案例,本地实际结果运行展示如下,仅供参考:

代码解析

根据如上我所给出的案例demo,着重进行代码解析,希望能够辅助大家理解。

如上案例代码展示了如何使用 Java 中的多线程来并行执行任务。它创建了两个线程,并模拟了线程任务的执行。下面是代码逐步解析:

1. Thread thread1 = new Thread(() -> { ... });

  • 这里创建了一个 Thread 对象 thread1,并通过 Lambda 表达式实现了线程的 run() 方法。这个线程会执行以下操作:
    • Thread.sleep(1000);:模拟任务执行,线程休眠 1000 毫秒(即 1 秒钟),表示任务正在执行。
    • System.out.println("Thread 1 completed");:任务执行完毕后,打印 "Thread 1 completed"

2. Thread thread2 = new Thread(() -> { ... });

  • 类似地,创建了第二个线程 thread2,并通过 Lambda 表达式指定线程的任务:
    • Thread.sleep(1500);:模拟任务执行,线程休眠 1500 毫秒(即 1.5 秒钟)。
    • System.out.println("Thread 2 completed");:任务执行完毕后,打印 "Thread 2 completed"

3. thread1.start();thread2.start();

  • start() 方法用于启动线程,调用 start() 后线程进入可运行状态,并开始执行其 run() 方法中的代码。在这两行代码中,thread1thread2 会并发执行,也就是说两个线程几乎同时开始运行。

4. thread1.join();thread2.join();

  • join() 方法用于让主线程(main)等待指定线程执行完成。调用 thread1.join() 会让主线程等待 thread1 完成;同样,调用 thread2.join() 会让主线程等待 thread2 完成。
  • 主线程在这两行代码后暂停执行,直到 thread1thread2 都执行完毕。

5. System.out.println("All threads completed");

  • 一旦两个线程都执行完毕,主线程继续执行并打印 "All threads completed"

异常处理

  • Thread.sleep() 方法会抛出 InterruptedException,因此在每个线程的 run() 方法中,使用 try-catch 块来捕获并处理这个异常,防止线程被中断时未处理异常导致程序崩溃。
  • 主线程中的 join() 也可能抛出 InterruptedException,因此使用 try-catch 块捕获并处理。

程序的输出

程序的输出会如下所示,但顺序可能有所不同,因为线程是并发执行的:

json 复制代码
Thread 1 completed
Thread 2 completed
All threads completed
  • 为什么输出顺序可能不一致?
    • 因为 thread1thread2 是并发执行的,它们的执行顺序是不可预测的。虽然 thread1 会在 1 秒后完成,thread2 会在 1.5 秒后完成,但它们的执行顺序仍然取决于操作系统调度。

小结

如上案例代码展示了如何使用 Java 中的多线程来执行并行任务。关键点包括:

  • 使用 Thread 类来创建和启动线程。
  • 使用 join() 方法让主线程等待其他线程完成。
  • 使用 Thread.sleep() 来模拟任务执行的时间。

通过这种方式,你可以让程序同时执行多个任务,从而提高效率,尤其是在需要等待外部资源或执行耗时操作时。

应用场景演示

1. 多任务并发处理

使用 start()run() 方法,我们可以轻松实现多任务并发处理。例如,在 Web 服务中,我们可以通过多线程处理多个用户请求,从而提高系统的吞吐量和响应速度。

2. 控制线程执行顺序

使用 join() 方法,我们可以确保线程按特定顺序执行。例如,在文件下载的场景中,我们可能需要先下载某些依赖文件,下载完成后再下载主文件,这时就可以使用 join() 来实现线程的同步。

3. 线程的中断处理

在一些长时间运行的任务中,可能需要通过 interrupt() 方法来中断某些不再需要的线程。例如,在数据处理过程中,如果检测到某个条件不再需要继续处理数据时,我们可以中断相关线程。

优缺点分析

优点:

  • 简单易用Thread 类提供的这些方法非常直观,开发者可以快速上手。
  • 灵活性高 :通过合理使用 sleep()join()interrupt() 等方法,我们可以精确控制线程的执行过程。
  • 线程安全 :通过合理的同步机制,Thread 类能够很好地支持多线程环境中的任务处理。

缺点:

  • 性能问题 :频繁使用 sleep() 会导致线程的浪费,影响程序的性能。
  • 难以调试:多线程程序的调试比单线程程序更为复杂,线程间的竞争条件和死锁问题可能难以发现和解决。
  • 资源消耗:线程的创建和销毁会消耗一定的系统资源,过多的线程会导致系统负担过重。

小结

通过本文的学习,我们对 Java 中 Thread 类的五个常用方法有了更深刻的理解。这些方法在多线程开发中扮演着至关重要的角色,掌握它们能够帮助我们更高效地进行并发编程。

总结

多线程编程是现代软件开发中不可或缺的一部分,合理使用 Thread 类的方法,能够有效提升程序的性能和响应速度。通过本文的讲解,希望大家能够熟练掌握这些方法,在实际开发中游刃有余地处理多线程任务。

寄语

希望每一位开发者都能在多线程编程的道路上越走越远。多线程的世界虽复杂,但只要你掌握了核心技巧,它就会为你的程序提供强大的动力。不断探索,挑战更复杂的并发问题,最终你会成为多线程编程的高手!

最后,大家如果觉得看了本文有帮助的话,麻烦给不熬夜崽崽点个三连(点赞、收藏、关注)支持一下哈,大家的支持就是我写作的无限动力。

最后

大家如果觉得看了本文有帮助的话,麻烦给不熬夜崽崽点个三连(点赞、收藏、关注)支持一下哈,大家的支持就是我写作的无限动力。

相关推荐
终身学习基地4 分钟前
第二篇:go包管理
开发语言·后端·golang
图南随笔22 分钟前
Spring Boot(二十一):RedisTemplate的String和Hash类型操作
java·spring boot·redis·后端·缓存
吃饭了呀呀呀22 分钟前
🐳 《Android》 安卓开发教程 - 三级地区联动
android·java·后端
shengjk134 分钟前
SparkSQL Join的源码分析
后端
Linux编程用C35 分钟前
Rust编程学习(一): 变量与数据类型
开发语言·后端·rust
uhakadotcom42 分钟前
一文读懂DSP(需求方平台):程序化广告投放的核心基础与实战案例
后端·面试·github
麓殇⊙43 分钟前
mybatis--多对一处理/一对多处理
java·tomcat·mybatis
Python私教1 小时前
Java手写链表全攻略:从单链表到双向链表的底层实现艺术
java·python·链表
吴生43961 小时前
数据库ALGORITHM = INSTANT 特性研究过程
后端