ExecutorService如何提交任务
在 Java 中,ExecutorService 提供了多种提交任务的方式,最常用的是 execute 和 submit。下面按常见用法系统说明,并给出示例。
一、创建 ExecutorService
先创建一个线程池(常见方式):
ExecutorService executor = Executors.newFixedThreadPool(3);
或(推荐,更可控):
ExecutorService executor = new ThreadPoolExecutor(
3,
5,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10)
);
二、提交任务的几种方式
✅ 1. execute(Runnable) —— 无返回结果
特点
- 只能提交
Runnable - 没有返回值
- 不能获取任务执行结果或异常
executor.execute(() -> {
System.out.println("任务执行中");
});
✅ 适合:不需要返回结果的任务
✅ 2. submit(Runnable) —— 返回 Future
Future> future = executor.submit(() -> {
System.out.println("任务执行中");
});
- 返回
Future> - 可用于:
- 判断任务是否完成
- 取消任务
- 但
future.get()返回null
future.get(); // 会阻塞,直到任务完成
✅ 3. submit(Runnable, T result) —— 返回指定结果
Future future = executor.submit(() -> {
System.out.println("任务执行中");
}, "SUCCESS");
String result = future.get();
System.out.println(result); // SUCCESS
✅ 4. submit(Callable) —— 有返回结果(最常用)
特点
- 支持返回结果
- 支持抛出异常
Callable task = () -> {
Thread.sleep(1000);
return "任务结果";
};
Future future = executor.submit(task);
String result = future.get(); // 阻塞等待结果
System.out.println(result);
三、execute vs submit 对比
| 方式 | 是否有返回值 | 是否可捕获异常 | 适用场景 |
|---|---|---|---|
execute |
❌ | ❌ | 简单异步任务 |
submit |
✅ | ✅ | 需要结果或异常处理 |
四、批量提交任务
✅ invokeAll
List> tasks = List.of(
() -> "任务1",
() -> "任务2"
);
List> futures = executor.invokeAll(tasks);
for (Future f : futures) {
System.out.println(f.get());
}
- 阻塞
- 所有任务完成后返回
✅ invokeAny
String result = executor.invokeAny(tasks);
System.out.println(result);
- 返回最快完成的任务结果
- 其余任务会被取消
五、关闭线程池(非常重要)
executor.shutdown(); // 不再接受新任务
或:
executor.shutdownNow(); // 尝试中断正在执行的任务
六、常见错误示例 ❌
executor.submit(() -> {
throw new RuntimeException("error");
});
❗异常不会抛出,而是藏在 Future 里:
Future> f = executor.submit(...)
f.get(); // 这里才会抛异常
七、总结一句话
没有返回结果 →
execute
有返回结果 / 需要异常处理 →submit(Callable)
如果你需要,我也可以结合 CompletableFuture、Spring @Async 或 实际业务场景 给你更贴近实战的示例。