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

Java中创建线程的几种方式

目录

Java 创建线程的几种方式

一、继承 Thread 类

核心原理

实现步骤

代码示例

简化写法(Lambda 表达式)

优缺点

二、实现 Runnable 接口

核心原理

实现步骤

代码示例

简化写法(Lambda 表达式)

优缺点分析

三、实现 Callable 接口

核心原理

实现步骤

代码示例

简化写法(Lambda 表达式)

优缺点分析

四、使用线程池

核心原理

线程池的 7 个核心参数

常见拒绝策略

线程池的使用步骤

代码示例

注意事项

总结对比


Java 创建线程的几种方式

在 Java 中,创建线程主要有 4 种经典方式:继承 Thread 类实现 Runnable 接口实现 Callable 接口使用线程池。本文将结合原理分析、代码示例和场景对比,系统讲解这四种方式的实现细节与差异。

一、继承 Thread 类

核心原理

Thread类是 Java 线程的核心基类,通过继承Thread并重写其run()方法(定义线程执行逻辑),即可创建一个自定义线程。启动线程需调用start()方法(而非直接调用run(),否则会退化为普通方法调用)。

实现步骤

  1. 自定义类继承Thread
  2. 重写run()方法(线程的核心执行逻辑);
  3. 创建自定义类实例,调用start()启动线程。

代码示例

public class ThreadTest1 {public static void main(String[] args) {// 创建并启动线程Thread t = new MyThread();t.start();  // 主线程逻辑for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出:" + i);}}
}// 自定义线程类(继承Thread)
class MyThread extends Thread {@Overridepublic void run() {// 线程执行逻辑for (int i = 1; i <= 5; i++) {System.out.println("子线程MyThread输出:" + i);}}
}

简化写法(Lambda 表达式)

public class CreateThread1 {public static void main(String[] args) {// 使用Lambda表达式直接定义线程逻辑Thread t1 = new Thread(() -> {System.out.println("子线程输出");});t1.start();}
}

优缺点

  • 优点:实现简单,直接操作线程对象;
  • 缺点:Java 单继承限制(若已继承其他类则无法使用);

二、实现 Runnable 接口

核心原理

Runnable是一个函数式接口(仅含run()方法),通过实现该接口定义线程任务(逻辑),再将任务交给Thread对象执行。这种方式将 “线程任务” 与 “线程对象” 解耦,更符合面向对象设计。

实现步骤

  1. 自定义类实现Runnable接口;
  2. 重写run()方法(定义任务逻辑);
  3. 创建任务实例,通过new Thread(runnable)绑定到线程对象;
  4. 调用start()启动线程。

代码示例

public class ThreadTest2 {public static void main(String[] args) {// 创建任务对象Runnable target = new MyRunnable();// 绑定线程并启动new Thread(target).start();// 主线程逻辑for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出 ===》" + i);}}
}// 自定义任务类(实现Runnable)
class MyRunnable implements Runnable {@Overridepublic void run() {// 任务执行逻辑for (int i = 1; i <= 5; i++) {System.out.println("子线程输出 ===》" + i);}}
}

简化写法(Lambda 表达式)

public class CreateThread2 {public static void main(String[] args) {// Lambda直接定义任务逻辑Thread t1 = new Thread(() -> System.out.println("子线程输出"));t1.start();System.out.println("主线程输出");}
}

优缺点分析

  • 优点:避免单继承限制;任务与线程解耦,灵活性高;
  • 缺点:无法直接获取线程执行结果(需结合其他机制)。

三、实现 Callable 接口

核心原理

Callable接口(Java 1.5 引入)与Runnable类似,但支持返回线程执行结果抛出检查异常。需通过FutureTask(实现了RunnableFuture接口)将Callable任务封装为可执行对象,再交给Thread执行。FutureTask支持通过get()方法获取线程结果(阻塞等待)。

实现步骤

  1. 自定义类实现Callable接口(指定返回值类型);
  2. 重写call()方法(定义带返回值的任务逻辑);
  3. 创建Callable实例,通过FutureTask封装;
  4. FutureTask交给Thread启动;
  5. 调用FutureTask.get()获取结果(阻塞等待线程完成)。

代码示例

// 自定义Callable任务(计算1到n的和)
class MyCallable implements Callable<String> {private int n;public MyCallable(int n) {this.n = n;}@Overridepublic String call() throws Exception {int sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return "线程求出了1-" + n + "的和是:" + sum;}
}public class ThreadTest3 {public static void main(String[] args) throws Exception {// 创建Callable任务Callable<String> call1 = new MyCallable(100);Callable<String> call2 = new MyCallable(200);// 封装为FutureTaskFutureTask<String> f1 = new FutureTask<>(call1);FutureTask<String> f2 = new FutureTask<>(call2);// 启动线程new Thread(f1).start();new Thread(f2).start();// 获取结果(阻塞等待)System.out.println(f1.get());  // 输出:线程求出了1-100的和是:5050System.out.println(f2.get());  // 输出:线程求出了1-200的和是:20100}
}

简化写法(Lambda 表达式)

public class CreateThread3 {public static void main(String[] args) throws Exception {// Lambda直接定义Callable逻辑FutureTask<String> futureTask = new FutureTask<>(() -> "hello, Callable");Thread t1 = new Thread(futureTask);t1.start();// 获取线程结果System.out.println("子线程返回的结果:" + futureTask.get());  // 输出:hello, Callable}
}

优缺点分析

  • 优点:支持返回值和异常抛出;适合需要异步计算结果的场景;
  • 缺点:需结合FutureTask使用,实现略复杂;get()方法可能阻塞主线程。

四、使用线程池

核心原理

线程池(ThreadPoolExecutor)是 Java 并发包(java.util.concurrent)提供的线程管理工具,通过复用线程避免频繁创建 / 销毁线程的开销,提高性能和稳定性。线程池支持统一管理线程的创建、调度和监控。

线程池的 7 个核心参数

使用ThreadPoolExecutor构造函数时需指定以下参数:

参数说明
corePoolSize核心线程数(长期保留的活跃线程数)
maximumPoolSize最大线程数(线程池允许的最大线程数)
keepAliveTime非核心线程的空闲存活时间(超时后销毁)
unitkeepAliveTime的时间单位(如TimeUnit.SECONDS
workQueue任务队列(存储待执行的任务,如ArrayBlockingQueue
threadFactory线程工厂(用于创建线程,默认Executors.defaultThreadFactory()
handler拒绝策略(任务队列和线程池均满时的处理方式)

常见拒绝策略

  • AbortPolicy(默认):直接抛出RejectedExecutionException
  • DiscardPolicy:丢弃新任务,不报错;
  • DiscardOldestPolicy:丢弃队列中最旧的任务,尝试重新提交新任务;
  • CallerRunsPolicy:由调用线程(如主线程)直接执行任务。

线程池的使用步骤

  1. 初始化ThreadPoolExecutor(指定核心参数);
  2. 通过submit()execute()提交任务(submit()支持返回Future);
  3. 任务执行完毕后,调用shutdown()shutdownNow()关闭线程池。

代码示例

import java.util.concurrent.*;public class CreateThread4 {public static void main(String[] args) throws Exception {// 初始化线程池(核心参数示例)ThreadPoolExecutor pool = new ThreadPoolExecutor(2,               // 核心线程数:25,               // 最大线程数:510,              // 空闲存活时间:10TimeUnit.SECONDS, // 时间单位:秒new ArrayBlockingQueue<>(3),  // 任务队列:容量3的阻塞队列Executors.defaultThreadFactory(),  // 默认线程工厂new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略:直接报错);// 提交任务(支持返回Future)Future<String> future = pool.submit(() -> {System.out.println("子线程执行任务");return "任务执行完成";});// 获取任务结果(阻塞等待)System.out.println("子线程返回的结果:" + future.get());  // 输出:任务执行完成// 关闭线程池(不再接受新任务,等待现有任务完成)pool.shutdown();}
}

注意事项

  • 合理配置参数:根据任务类型(CPU 密集型 / IO 密集型)调整核心线程数和队列容量;
  • 正确关闭线程池:避免调用shutdownNow()(可能强制终止未完成任务);
  • 监控与调优:通过getActiveCount()getQueue().size()等方法监控线程池状态,优化参数配置。

总结对比

方式核心接口 / 类是否支持返回值优点适用场景
继承 Thread 类Thread实现简单简单任务,无继承冲突场景
实现 Runnable 接口Runnable解耦任务与线程,避免单继承限制多线程共享任务逻辑
实现 Callable 接口Callable+FutureTask支持返回值和异常,适合异步计算需要获取线程执行结果的场景
使用线程池ThreadPoolExecutor是(通过submit复用线程,降低开销,便于管理高并发、长期运行的任务

http://www.xdnf.cn/news/8150.html

相关文章:

  • 【C++/控制台】简易五子棋游戏
  • LeetCode 257. 二叉树所有路径求解:回溯算法的深度解析与实践
  • 力扣热题——罗马数字转整数
  • 降低诊断消息转发延迟与缓冲区内存占用优化方案
  • Ubuntu 通过指令远程命令行配置WiFi连接
  • StickyNotes,简单便签超实用
  • Oracle 数据文件被删除后使用rman备份恢复过程
  • AI大模型应用之评测篇
  • 为什么自适应调零抗干扰天线不能做RTK之二
  • 前端JavaScript-对象-同Python及C++对比
  • Labview基础使用教程
  • 算法--js--组合总和
  • leetcode2947. 统计美丽子字符串 I-medium
  • Spring声明式事务源码全链路剖析与设计模式深度解读
  • 【动手学深度学习】2.1. 数据操作
  • Python训练打卡Day31
  • [Harmony]实现JSON与类的双向转换
  • embedding的微调
  • MYSQL order 、group 与row_number详解
  • 3452. 好数字之和
  • 通义灵码 2.5 版深度评测:智能编程的边界在哪里?
  • 在 Spring 管理的事务环境中,获取当前事务下的 JDBC Connection对象
  • 每日算法 -【Swift 算法】Z 字形变换(Zigzag Conversion)详解与实现
  • 【机器学习基础】机器学习入门核心算法:线性回归(Linear Regression)
  • 课外知识:Python方法绑定机制与装饰器传参详解 与 实战
  • 力扣HOT100之二叉树:105. 从前序与中序遍历序列构造二叉树
  • std::initialzer_list 与花括号{}数据列表
  • 实现一个前端动态模块组件(Vite+原生JS)
  • Springboot安全策略Spring Security
  • LeetCode Hot100(滑动窗口)