理解 Java Executor Framework 的核心作用与优势
掌握 Executor、ExecutorService 与 ScheduledExecutorService 等关键接口的使用方式
能够根据应用场景选择合适的线程池类型
学会提交 Callable 任务并处理返回结果
掌握执行器资源的正确关闭方式
Java 的 Executor 是 java.util.concurrent 包中的一部分,自 Java 5 引入。它提供了一套高级 API,用于管理和调度线程任务,开发者无需手动创建或控制线程,框架会自动处理任务的调度与执行。该框架的核心思想是 将任务提交与任务执行解耦,从而简化并发编程。

Executor 是整个框架的根接口,仅定义了一个方法:
void execute(Runnable command);它隐藏了线程创建细节。例如:
Executor executor = command -> new Thread(command).start();
executor.execute(() -> System.out.println("任务已执行"));注意:实际开发中很少直接实现
Executor,通常使用其子接口。
ExecutorService 扩展了 Executor,提供了更丰富的功能:
支持 Runnable 和 Callable 两种任务类型
可以获取任务执行结果(通过 Future)
提供生命周期管理方法(如 shutdown()、awaitTermination())
支持批量任务提交(如 invokeAll())
示例:
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(() -> System.out.println("正在执行任务"));
service.shutdown();ScheduledExecutorService 继承自 ExecutorService,专用于定时或周期性任务:
schedule(Runnable, delay, unit):延迟执行一次
scheduleAtFixedRate(task, initialDelay, period, unit):固定频率执行
scheduleWithFixedDelay(...):固定延迟执行(上一次结束到下一次开始)
示例:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> System.out.println("每5秒执行一次"), 0, 5, TimeUnit.SECONDS);这是 ExecutorService 最常用的实现类,支持高度自定义:
可配置核心线程数(corePoolSize)与最大线程数(maximumPoolSize)
可指定任务队列容量
支持自定义线程工厂(ThreadFactory)
可设置拒绝策略(如抛异常、丢弃任务等)
虽然通常通过 Executors 工厂类创建,但理解其内部机制对调优至关重要。
为 ExecutorService 提供了默认实现(如 submit()、invokeAll()),便于开发者构建自定义执行器
Java 通过 Executors 工具类提供多种预设线程池:
注意:在生产环境中,建议避免直接使用
Executors创建线程池,而应使用ThreadPoolExecutor显式配置参数,防止资源耗尽。
提交 Callable 任务并获取结果
以下程序演示如何创建一个返回字符串结果的任务,并通过 Future 获取执行结果。
import java.util.concurrent.*;
class GreetingTask implements Callable<String> {
private String name;
public GreetingTask(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
return "你好," + name + "!";
}
}
public class Main {
public static void main(String[] args) {
// 创建任务实例
GreetingTask task = new GreetingTask("开发者社区");
// 创建固定大小为 4 的线程池
ExecutorService executor = Executors.newFixedThreadPool(4);
// 提交任务,获得 Future 对象
Future<String> future = executor.submit(task);
try {
// 阻塞等待任务完成并获取结果
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
System.err.println("任务执行过程中发生错误");
e.printStackTrace();
} finally {
// 关闭线程池,释放资源
executor.shutdown();
}
}
}输出结果:
你好,开发者社区!关键点说明:
Callable 与 Runnable 不同,可返回结果并抛出受检异常
submit() 方法返回 Future<T>,用于获取结果或取消任务
必须调用 shutdown() 优雅关闭线程池,否则 JVM 可能无法退出
Executor Framework 将“任务”与“执行机制”分离,极大简化并发编程
ExecutorService 是日常开发中最常用的接口
Callable + Future 组合可用于获取异步计算结果
不同线程池适用于不同场景:单线程保序、固定池控资源、缓存池应对突发流量
务必在使用完毕后调用 shutdown(),避免线程泄漏
为什么在生产环境中不推荐直接使用 Executors.newCachedThreadPool()?可能带来什么风险?
scheduleAtFixedRate 和 scheduleWithFixedDelay 在任务执行时间超过间隔时间时,行为有何不同?
如果不调用 executorService.shutdown(),程序会有什么表现?如何验证?