当前位置: 首页 > news >正文

Java 创建线程的几种方式

在 Java 中,创建线程主要有以下几种方式。下面我将详细解释每种方式,并提供代码示例。

1. 继承 Thread 类

这是最基础的创建线程方式,通过继承 Thread 类并重写 run() 方法。

public class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程运行中: " + Thread.currentThread().getName());}
}// 使用方式
public class Main {public static void main(String[] args) {MyThread thread = new MyThread();thread.start(); // 启动线程}
}

特点

  • 简单直接
  • 由于 Java 是单继承,这种方式会占用继承位置
  • 线程与任务耦合在一起

2. 实现 Runnable 接口

更常用的方式是实现 Runnable 接口,将线程和任务解耦。

public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程运行中: " + Thread.currentThread().getName());}
}// 使用方式
public class Main {public static void main(String[] args) {Thread thread = new Thread(new MyRunnable());thread.start();// 或者使用 Lambda 表达式(Java 8+)Thread lambdaThread = new Thread(() -> {System.out.println("Lambda 线程运行中: " + Thread.currentThread().getName());});lambdaThread.start();}
}

特点

  • 推荐使用的方式
  • 线程与任务分离,更灵活
  • 可以实现多个接口,不影响类继承结构

3. 实现 Callable 接口

CallableRunnable 类似,但可以返回结果和抛出异常。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;public class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(1000); // 模拟耗时操作return "任务执行完成: " + Thread.currentThread().getName();}
}// 使用方式
public class Main {public static void main(String[] args) throws Exception {FutureTask<String> futureTask = new FutureTask<>(new MyCallable());Thread thread = new Thread(futureTask);thread.start();// 获取执行结果(会阻塞直到任务完成)String result = futureTask.get();System.out.println(result);}
}

特点

  • 可以返回执行结果
  • 可以抛出异常
  • 需要配合 FutureTask 或线程池使用

4. 使用线程池(ExecutorService)

在实际开发中,最推荐使用线程池来管理线程,提高资源利用率。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class ThreadPoolExample {public static void main(String[] args) {// 创建固定大小的线程池ExecutorService executor = Executors.newFixedThreadPool(3);// 提交任务for (int i = 0; i < 5; i++) {final int taskId = i;executor.submit(() -> {System.out.println("任务 " + taskId + " 执行中: " + Thread.currentThread().getName());try {TimeUnit.MILLISECONDS.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}});}// 关闭线程池executor.shutdown();try {// 等待所有任务完成if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();}}
}

特点

  • 管理和复用线程,减少创建销毁开销
  • 控制并发线程数量
  • 提供任务队列、定时执行等功能

5. 使用 CompletableFuture (Java 8+)

Java 8 引入的 CompletableFuture 提供了更强大的异步编程能力。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureExample {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建异步任务CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "异步任务结果";});// 处理任务结果future.thenAccept(result -> {System.out.println("处理结果: " + result);});// 等待任务完成future.get();}
}

6. 使用 Spring 的 @Async 注解

在 Spring 框架中,可以使用 @Async 注解轻松创建异步方法。

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;@EnableAsync
@Component
public class AsyncService {@Asyncpublic void asyncMethod() {System.out.println("异步方法执行: " + Thread.currentThread().getName());}
}// 在 Controller 或 Service 中调用
asyncService.asyncMethod();

对比总结

创建方式优点缺点适用场景
继承 Thread简单直接占用继承位置,耦合度高简单测试或demo
实现 Runnable灵活,解耦不能直接返回结果大多数场景
实现 Callable可返回结果,可抛异常使用稍复杂需要返回结果的异步任务
线程池资源复用,功能强大配置稍复杂生产环境,高并发场景
CompletableFuture功能强大,链式编程Java 8+ 支持复杂异步编程
Spring @Async集成简单,注解驱动需要 Spring 环境Spring 项目中的异步处理

最佳实践建议

  1. 优先使用线程池而不是直接创建线程,避免资源浪费
  2. 实现 Runnable 接口比继承 Thread 类更灵活
  3. 需要返回值时使用 Callable 和 Future
  4. 在 Spring 项目中使用 @Async 注解简化异步编程
  5. 对于复杂异步流程,使用 CompletableFuture
  6. 始终处理线程中的异常,避免 silent failure
// 异常处理示例
Thread thread = new Thread(() -> {try {// 任务代码} catch (Exception e) {System.err.println("线程执行异常: " + e.getMessage());}
});
thread.setUncaughtExceptionHandler((t, e) -> {System.err.println("线程 " + t.getName() + " 发生异常: " + e.getMessage());
});
thread.start();

根据具体需求选择合适的线程创建方式,可以提高代码的可维护性和性能。

http://www.dtcms.com/a/349186.html

相关文章:

  • Python复数运算完全指南:从基础到工程级应用实践
  • Hyperledger Fabric官方中文教程-改进笔记(十六)-策略(policy)
  • 【Luogu】P4127 [AHOI2009] 同类分布 (数位DP)
  • 【知识杂记】卡尔曼滤波相关知识高频问答
  • Java 中 Set 接口(更新版)
  • 深度学习中的“集体智慧”:Dropout技术详解——不仅是防止过拟合,更是模型集成的革命
  • Java静态代理与动态代理实战解析
  • redis集群模式 -批量操作
  • 智慧工业设备巡检误报率↓81%!陌讯多模态融合算法实战优化与边缘部署
  • 【机器学习】6 Frequentist statistics
  • (计算机网络)JWT三部分及 Signature 作用
  • 车企数据资产管理——解读46页大型车企数据资产数据治理体系解决方案【附全文阅读】
  • 计算机系统 C语言运行时对应内存映射 以及 各个段的数据访问下标越界产生的后果
  • Delphi 12 基于 Indy 的 WebServer 的 https 实现的问题
  • HiRAG:用分层知识图解决复杂推理问题
  • ruoyi框架角色分配用户
  • imx6ull-驱动开发篇38——Linux INPUT 子系统
  • leetcode_189 轮转数组
  • 什么嵌入式接入大模型:第二篇基于 STM32 ESP32 的社会服务助手
  • AI重塑跨境电商:选品成功率提升53%+物流效率加快34%,多语种运营成破局关键
  • String的intern方法
  • 数据库服务优化设置
  • nano命令使用方法
  • 备考NCRE三级信息安全技术 --- L1 信息安全保障概述
  • 自编 C# 颜色命名和色彩显示,使用 DataGridView 展示颜色命名、RGB值
  • 推进数据成熟度旅程的 3 个步骤
  • 基于 MATLAB 的信号处理实战:滤波、傅里叶变换与频谱分析
  • 什么是IP代理
  • 智慧农业病虫害监测误报率↓82%!陌讯多模态融合算法实战解析
  • 基于微信小程序校园微店源码