Java 线程的三种创建方式详解

在 Java 多线程编程中,创建线程的方式主要有三种:继承Thread类、实现Runnable接口、实现Callable接口结合FutureTask。每种方式都有其独特的应用场景和特性,本文将通过具体代码示例和面试题解析深入分析。

一、通过继承 Thread 类实现线程

核心原理

继承Thread类并重写run()方法,run()内定义线程执行逻辑。通过start()方法启动线程,而非直接调用run()。

代码示例

package day13;

public class TestThread extends Thread {

    @Override
    public void run() {
        // 获取当前线程名称(主线程为"main",子线程格式为"Thread-序号")
        String threadName = Thread.currentThread().getName();
        
        for (int i = 0; i < 10; i++) {
            System.out.println(threadName + " 当前循环:" + i);
        }
    }

    public static void main(String[] args) {
        TestThread t1 = new TestThread();
        TestThread t2 = new TestThread();

        // 注意:直接调用run()会作为普通方法执行,不会创建新线程
        // t1.run();
        // t2.run();

        // 正确方式:通过start()启动新线程
        t1.start();
        t2.start();
    }
}
 

执行逻辑说明

  1. start () 与 run () 的本质区别
    • start():触发 JVM 创建新线程,线程状态从NEW变为RUNNABLE(就绪态),由 CPU 调度执行run()方法,实现多线程并发。
    • run():若直接调用,等同于主线程内的普通方法调用,按顺序执行,无并发效果。

二、通过实现 Runnable 接口实现线程

核心原理

将线程任务(run()方法)与线程对象(Thread)分离,解耦任务逻辑与线程管理,支持资源共享。

代码示例


public class TestRunnable implements Runnable {
    // 共享变量,两个线程共同操作
    private int sum = 0;

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        for (int i = 2; i <= 100; i += 2) {
            sum += i;
            System.out.println(threadName + " 当前累加和:" + sum);
        }
    }

    public static void main(String[] args) {
        // 创建共享任务实例
        TestRunnable sharedTask = new TestRunnable();
        
        // 创建两个线程共享同一个任务
        Thread threadA = new Thread(sharedTask, "线程A");
        Thread threadB = new Thread(sharedTask, "线程B");
        threadA.start();
        threadB.start();

        // 使用Lambda表达式创建线程(Java 8+)
        new Thread(() -> {
            System.out.println(
                Thread.currentThread().getName() + " 通过Lambda创建"
            );
        }, "线程C").start();
    }
}
 

核心优势

  • 资源共享:多个线程可共享同一个Runnable实例(如示例中的task),方便实现数据共享(如多线程售票系统中的共享票数)。
  • 消除单继承限制:允许类在实现Runnable的同时继承其他类,提高代码扩展性。
  • 函数式接口支持:可通过 Lambda 表达式简化代码,提升编程效率(如主线程中的匿名内部类简化)。

三、通过实现 Callable 接口结合 FutureTask 实现线程

核心原理

Callable是增强版Runnable,支持返回值和异常抛出,需通过FutureTask包装后与Thread配合使用。

代码示例

import java.util.concurrent.*;

public class TestCallable implements Callable<Integer> {
    
    @Override
    public Integer call() throws Exception {
        String threadName = Thread.currentThread().getName();
        int sum = 0;
        
        for (int i = 1; i <= 100; i++) {
            sum += i;
            Thread.sleep(300); // 模拟耗时操作
            System.out.println(threadName + " 当前累计和:" + sum);
        }
        
        return sum;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        TestCallable task = new TestCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(task);
        
        Thread workerThread = new Thread(futureTask, "计算线程");
        workerThread.start();
        
        // 阻塞等待计算结果
        int total = futureTask.get();
        System.out.println("1-100的总和为:" + total);
    }
}
 

关键特性

  • 返回值支持:call()方法可通过return返回泛型结果(如示例中的Integer),适用于需要异步计算结果的场景(如分布式计算、耗时 IO 操作)。
  • 异常处理:允许抛出受检异常(如InterruptedException),调用端通过try-catch或声明抛出处理,比Runnable的run()更灵活。
  • FutureTask 的作用
    • 作为Thread的参数,桥接Callable与线程;
    • 提供get()方法阻塞获取结果、cancel()取消任务、isDone()判断任务是否完成等功能。

Runnable 与 Callable 的区别?

特性

Runnable

Callable

方法名

run()(无返回值)

call()(有泛型返回值)

异常处理

只能捕获异常,不能声明抛出

可声明抛出受检异常

返回值

支持泛型返回值

使用方式

直接作为Thread参数

需通过FutureTask包装后使用

四、三种方式对比与适用场景

创建方式

继承 Thread 类

实现 Runnable 接口

实现 Callable+FutureTask

核心特点

简单直观,耦合度高

解耦任务与线程,支持资源共享

支持返回值和异常处理

继承限制

受单继承限制

无限制(可继承其他类)

无限制

返回值

有(通过 FutureTask 获取)

适用场景

简单独立任务

多线程资源共享场景

需要异步计算结果的场景

典型应用

独立日志输出线程

多线程售票系统

分布式计算结果汇总

总结

  • Thread 类:适合简单独立任务,但受单继承限制,扩展性较弱。
  • Runnable 接口:推荐优先使用,解耦任务逻辑与线程,支持资源共享和 Lambda 简化,适用于大多数多线程场景。
  • Callable+FutureTask:在需要获取线程执行结果或处理异常时使用,如异步计算、任务调度等复杂场景。

掌握这三种创建方式的核心差异和适用场景,能帮助开发者在实际项目中更高效地利用多线程提升程序性能,同时应对面试中的高频问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值