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

【Java】多线程_创建线程的四种方式

在 Java 中,实现多线程编程是常见的开发任务。Java 提供了多种方式来创建和管理线程,满足不同场景下的需求。本文将详细介绍 Java 中创建线程的四种常见方式,包括:

  1. 继承 Thread
  2. 实现 Runnable 接口
  3. 实现 Callable 接口 + Future 获取返回值
  4. 使用线程池(ExecutorService

1.继承Tread类(基础)

步骤

  1. 定义一个子类继承 Thread,并重写 run() 方法。
  2. 创建该子类的实例,调用 start() 方法启动线程。
class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程执行:" + Thread.currentThread().getName());}
}public class Test {public static void main(String[] args) {Thread t = new MyThread();t.start();  // 启动线程(不是 run())}
}

原理

  • Thread 类本身实现了 Runnable 接口,其 run() 方法是线程执行的入口。
  • 调用 start() 方法会触发 JVM 创建一个新的操作系统级线程,并自动调用 run() 方法。

优点:简单直接,适合快速实现简单的多线程任务。

缺点

  • Java 不支持多继承,若子类已经继承了其他类,则无法再继承 Thread
  • 线程逻辑与线程对象绑定,扩展性差。

2.实现Runnable接口(常用)

步骤

  1. 定义一个类实现 Runnable 接口,并实现 run() 方法。
  2. 创建该类的实例,作为参数传递给 Thread 的构造函数。
  3. 调用 Thread 实例的 start() 方法启动线程。
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程执行:" + Thread.currentThread().getName());}
}public class Test {public static void main(String[] args) {Thread t = new Thread(new MyRunnable());t.start();}
}

原理:通过 new Thread(runnable) 创建新线程,本质仍是调用 Runnablerun()

优点

  • 任务逻辑(Runnable)与线程管理(Thread)分离,符合单一职责原则。
  • 多个线程可以共享同一个 Runnable 实例,便于资源共享。

缺点

  • 无返回值run() 方法无法返回计算结果。
  • 异常处理受限run() 不能抛出受检异常(子类重写方法时,不能抛出比父类更宽的受检异常),需自行捕获处理。

3.实现 Callable 接口 + FutureTask(有返回值)

步骤

  1. 定义一个类实现 Callable<T> 接口,并实现 call() 方法(可返回结果和抛出异常)。
  2. FutureTask 包装 Callable 实例。
  3. FutureTask 作为参数传递给 Thread 的构造函数,启动线程。
  4. 通过 FutureTask.get() 获取异步计算结果(阻塞直到任务完成)。
class MyCallable implements Callable<Integer> {@Overridepublic Integer call() {return 42;  // 可以有返回值}
}public class Test {public static void main(String[] args) throws Exception {FutureTask<Integer> task = new FutureTask<>(new MyCallable());Thread t = new Thread(task);t.start();// 阻塞等待结果Integer result = task.get();System.out.println("返回值:" + result);}
}

原理

  • FutureTask 实现了 RunnableFuture(继承 RunnableFuture),封装了 Callable
  • 调用 start() 时,Thread 执行 FutureTask.run(),内部调用 Callable.call() 并存储结果。
  • FutureTask.get() 用于获取线程执行结果(阻塞等待)。

优点:可以返回执行结果,支持异常处理。

缺点

  • 复杂性高:需配合 FutureTask 或线程池使用,代码复杂度增加。
  • 阻塞风险Future.get() 会阻塞当前线程,需合理设计超时机制。

4.使用线程池(Executor 框架)

1.如何创建线程池对象:用具类-> Executors
2.获取线程池对象:Executors中的静态方法:static ExecutorService newFixedThreadPool(int nThreads)  a.参数:指定线程池中最多创建的线程对象条数b.返回值ExecutorService 是线程池,用来管理线程对象3.执行线程任务: ExecutorService中的方法Future<?> submit(Runnable task) 提交一个Runnable任务用于执行 Future<T> submit(Callable<T> task) 提交一个Callable任务用于执行 4.submit方法的返回值:Future接口用于接收run方法或者call方法返回值的,但是run方法没有返回值,所以可以不用Future接收,执行call方法需要用Future接收Future中有一个方法:V get()  用于获取call方法返回值5. ExecutorService中的方法:void shutdown()  启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(2);// 提交Runnable任务
executor.execute(() -> System.out.println("线程池执行Runnable"));// 提交Callable任务并获取Future
Future<String> future = executor.submit(() -> "线程池执行Callable");
String result = future.get();
System.out.println(result);// 关闭线程池
executor.shutdown();

原理

  • 线程复用:通过维护一组核心线程(corePoolSize),避免频繁创建和销毁线程的开销。
  • 任务队列:当线程数达到核心线程数时,新任务进入阻塞队列(如 LinkedBlockingQueue)。
  • 动态扩容:若队列满且线程数未达最大线程数(maximumPoolSize),创建新线程处理任务。
  • 拒绝策略:当线程数达上限且队列满时,触发拒绝策略(如丢弃任务或抛出异常)。
  • 任务提交
    • execute(Runnable):提交无返回值的任务。
    • submit(Callable):提交有返回值的任务,返回 Future 对象。

优点

  • 复用线程,减少创建/销毁线程的开销。
  • 通过队列和最大线程数限制并发量,防止资源耗尽。
  • 支持任务调度、监控、统计等功能。

缺点

  • 配置复杂:需合理设置核心线程数、队列类型、拒绝策略等参数。
  • 潜在风险:不关闭线程池可能导致资源泄漏(需显式调用 shutdown())。

5.总结对比

特性继承Thread实现Runnable实现Callable线程池
返回值❌ 不支持❌ 不支持✅ 支持✅ 支持
异常处理❌ 需自行捕获❌ 需自行捕获✅ 可抛出受检异常✅ 支持
资源共享❌ 实例隔离✅ 可共享同一实例✅ 可共享同一实例✅ 通过队列共享
任务取消❌ 仅支持中断❌ 仅支持中断✅ 支持Future.cancel✅ 支持
扩展性❌ 受单继承限制✅ 高✅ 高✅ 极高(可配置参数)
任务与线程关系强耦合(线程即任务)解耦(任务独立)解耦(任务独立)完全解耦
线程管理方式手动创建/销毁手动管理手动或线程池管理线程池统一管理
资源开销高(频繁创建/销毁)中等中等低(线程复用)
线程启动方式JVM本地方法start0()包装为Thread执行包装为FutureTask执行线程池Worker循环执行
状态管理简单生命周期状态ThreadFutureTask状态机复杂的状态控制体系
创建开销每次new Thread高开销复用Runnable实例需包装FutureTask一次创建长期使用
内存泄漏风险高(线程未及时回收)中等中等低(需正确关闭)
并发控制能力❌ 需手动同步✅ 需同步控制✅ 需同步控制✅ 内置队列管理
OOM风险高(无节制创建线程)中等中等可控(有界队列配置)
简单独立任务✅ 适合✅ 适合❌ 过度设计❌ 资源浪费
资源共享任务❌ 不适合✅ 最佳✅ 适合✅ 适合
异步结果获取❌ 不支持❌ 不支持✅ 必须选择✅ 推荐
高并发请求处理❌ 绝对禁止❌ 不推荐❌ 不推荐✅ 唯一选择
定时/延迟任务❌ 不支持❌ 不支持❌ 不支持✅ 必须选择

相关文章:

  • 力扣第451场周赛
  • Java 的 synchronized
  • 在 Ubuntu linux系统中设置时区的方案
  • React从基础入门到高级实战:React 核心技术 - React Router:路由管理
  • 【操作系统】-4.3.1文件的层次结构
  • 计算机网络技术(二)
  • DAY33 简单神经网络
  • Leetcode 1651. Hopper 公司查询 III
  • 【NIPS 2024】Towards Robust Multimodal Sentiment Analysis with Incomplete Data
  • quill 富文本多张图片排序
  • 大语言模型的完整训练周期从0到1的体系化拆解
  • CS学习网站-geeksforgeeks介绍
  • 历年安徽大学保研上机真题
  • 原生php单元测试
  • Kafka 的日志清理策略:delete 和 compact
  • 决策引擎与规则引擎在交易所业务风控中的建设思路、架构设
  • 历年北京理工大学保研上机真题
  • 使用 Hyperlane 实现 WebSocket广播
  • MIT 6.S081 2020Lab5 lazy page allocation 个人全流程
  • 《技术择时,价值择股》速读笔记
  • 学术网站建设/百度一下首页官网
  • 网站建设预算策划/站长友情链接
  • 自己视频怎么上传网站/去了外包简历就毁了吗
  • 福州专业网站建设价格/seo搜论坛
  • 驻马店住房和城乡建设局网站/代运营公司哪家好一些
  • 做盈利网站怎么备案/批量查询收录