Java基础教程(134)多线程之创建线程:并发编程基石,深度剖析Java多线程的创生之道,附实战源码

深度分析Java多线程之创建新线程

在当今计算领域,多核处理器已成为标配,并发编程是释放硬件潜力、构建高性能应用的关键。Java从语言层面提供了强大的多线程支持,而一切并发故事的起点,便是如何正确地创建一个新线程。本文将深入浅出,剖析三种核心创建方式。

1. 继承Thread类:最直接的方式

这是最原始的方法。通过定义一个继承自java.lang.Thread类的子类,并重写其run()方法来实现线程逻辑。

示例:

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("通过继承Thread创建线程: " + Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 关键!启动新线程,JVM会自动调用run()
    }
}

深度分析:

  • 优点:写法简单,直接使用this即可获取当前线程对象。
  • 缺点:由于Java是单继承,继承了Thread后无法再继承其他类,严重限制了代码的灵活性。违反了“组合优于继承”的原则。
  • 本质:start()方法是一个本地方法(native),它会通知JVM启动一个新的系统级线程,然后由这个新线程去异步执行run()方法中的代码。直接调用run()方法则等同于普通方法调用,不会产生新线程。
2. 实现Runnable接口:更灵活的选择

这是推荐使用的更通用方式。定义一个实现了java.lang.Runnable接口的类,实现其run()方法,然后将该实例作为参数传递给Thread类的构造函数。

示例:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("通过实现Runnable创建线程: " + Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

深度分析:

  • 优点:
    • 解耦:将线程任务(Runnable)与线程本身(Thread)分离,任务定义更清晰。
    • 灵活:实现Runnable的类仍然可以继承其他类。
    • 共享资源:多个线程可以轻松共享同一个Runnable实例(任务),非常适合处理同一份资源,如卖票系统。

Lambda表达式简化:由于Runnable是函数式接口,在Java 8后可用Lambda极大简化:

new Thread(() -> {
    System.out.println("使用Lambda创建线程");
}).start();
3. 实现Callable接口:可带返回值的进阶

Runnablerun()方法没有返回值也不能抛出受检异常。java.util.concurrent.Callable接口的出现解决了这两个痛点。它的call()方法可以返回结果并抛出异常。

示例:

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return "Callable线程执行完毕,返回结果!";
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        Thread thread = new Thread(futureTask); // FutureTask实现了Runnable
        thread.start();

        String result = futureTask.get(); // 阻塞等待线程结束并获取返回值
        System.out.println(result);
    }
}

深度分析:

  • 优点:能够获取异步任务的执行结果,是现代异步编程(如CompletableFuture)的基础。
  • 核心:Callable实例不能直接传给Thread,需要用一个FutureTask类来包装它。FutureTask既实现了Runnable,又提供了get()等方法来管理Callable的生命周期和结果。调用get()方法会阻塞主线程,直到call()方法执行完成。
总结对比

方式

优点

缺点

适用场景

继承Thread

编码简单

单继承局限,灵活性差

快速原型、简单测试

实现Runnable

灵活性高,可继承其他类,支持资源共享

无法直接返回值

绝大多数场景的首选

实现Callable

可返回值,可抛出异常

使用稍复杂,需要FutureTask

包装

需要获取线程执行结果的异步任务

结论:
在实战中,优先选择Runnable接口(常结合Lambda表达式),因其设计更优雅、灵活。当需要处理返回值时,Callable+FutureTask是标准答案。理解这三种方式的底层机制和差异,是掌握Java并发编程、编写出高效且健壮代码的第一步。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值