Java线程池execute()和submit()的对比详解
作者:码不停蹄的玄黓
这段文章详细对比了execute()和submit()在Java线程池中的核心区别,包括返回值、异常处理及支持的任务类型,并提供了实战代码示例,关键词:execute()、submit()、线程池提交任务,需要的朋友可以参考下
execute() 和 submit() 都是线程池提交任务的核心方法,都属于 ExecutorService 线程池接口,核心区别:execute() 无返回值、不处理异常;submit() 有返回值、会捕获异常。
下面从核心定义、使用场景、返回值、异常处理、方法归属等维度做清晰对比,附实战代码。
一、核心区别速查表
| 对比项 | execute() | submit() |
|---|---|---|
| 返回值 | void,无返回结果 | Future<T>,可获取任务执行结果/状态 |
| 异常处理 | 直接抛出异常(会终止线程,从线程池移除) | 自动捕获异常,需通过 Future.get() 才抛出 |
| 任务类型 | 只能提交 Runnable 无返回值任务 | 可提交 Runnable + Callable 有返回值任务 |
| 使用场景 | 执行不需要结果、不关心异常的异步任务 | 执行需要结果、需要捕获异常的异步任务 |
| 方法归属 | 定义在 Executor 顶层接口 | 定义在 ExecutorService 子接口 |
| 源码设计 | 最基础的任务提交方法 | 基于 execute() 封装,功能更强 |
二、详细解析
1. 返回值区别(最核心)
- execute():
void,提交后无法跟踪任务是否执行完成、无法获取结果。 - submit():返回
Future对象,可通过它:- 判断任务是否完成
- 取消任务
- 获取任务执行结果
- 获取任务抛出的异常
2. 异常处理区别(关键坑点)
- execute():任务抛出未捕获异常时,直接打印堆栈、终止线程,线程会从线程池被移除。
- submit():无论任务抛什么异常,都不会直接抛出,异常会被存起来,只有调用
Future.get()时才会抛出。
3. 支持的任务类型区别
- execute():仅支持
Runnable(无返回值)。 - submit():支持两种任务:
Runnable(无返回值)Callable<T>(有返回值,能抛异常)
三、实战代码示例
1. execute() 使用
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecuteDemo {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
// 提交无返回值任务
pool.execute(() -> {
System.out.println("execute 执行任务");
// 异常会直接抛出,导致线程死亡
// int i = 1 / 0;
});
pool.shutdown();
}
}
✅ 适用:日志打印、消息发送、异步更新缓存等不需要结果、不关心异常的任务。
2. submit() 使用(获取返回值)
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SubmitDemo {
public static void main(String[] args) throws Exception {
ExecutorService pool = Executors.newSingleThreadExecutor();
// 提交 Callable 任务,有返回值
Future<Integer> future = pool.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("submit 执行任务");
return 1 + 1; // 返回结果
}
});
// 获取任务结果(阻塞等待)
Integer result = future.get();
System.out.println("任务结果:" + result); // 输出 2
pool.shutdown();
}
}
✅ 适用:异步计算、接口并行调用、需要获取执行结果/处理异常的任务。
3. submit() 异常处理演示
Future<Integer> future = pool.submit(() -> {
System.out.println("submit 任务");
int i = 1 / 0; // 抛异常
return 100;
});
// 异常不会直接抛出!
// 只有调用 get() 才会抛出 ExecutionException
try {
future.get();
} catch (Exception e) {
System.out.println("捕获到异常:" + e.getCause());
}
四、底层原理(简单理解)
submit() 本质是对 execute() 的封装:
- 把任务包装成
FutureTask(同时实现Runnable + Future) - 调用
execute()提交 - 执行结果/异常存入
FutureTask,通过get()获取
五、如何选择?
- 只用 execute():
任务不需要返回值、异常自己处理(try-catch)、不关心执行状态。 - 必须用 submit():
- 需要获取任务结果
- 需要判断任务是否完成/取消任务
- 需要统一捕获任务异常
- 提交
Callable带返回值的任务
总结
- execute():轻量、无返回、异常直接抛 → 适合简单异步执行。
- submit():强大、有返回、可捕获异常 → 适合需要结果/管控的任务。
- 日常开发:简单任务用 execute,复杂任务用 submit + Future。
以上就是Java线程池execute()和submit()的对比详解的详细内容,更多关于Java线程池execute()和submit()对比的资料请关注脚本之家其它相关文章!
