Java ExecutorService 类
ExecutorService 是 Java 并发编程中的一个核心接口,它属于 java.util.concurrent
包。
ExecutorService 提供了一种更高级的线程管理方式,允许开发者高效地执行异步任务,而无需手动创建和管理线程。
ExecutorService 的主要作用包括:
- 线程池管理:自动管理线程的生命周期,减少线程创建和销毁的开销。
- 任务调度:支持提交
Runnable
或Callable
任务,并返回Future
对象以跟踪任务执行状态。 - 资源优化:通过线程池复用线程,提高系统性能。
ExecutorService 的核心方法
ExecutorService 提供了多种方法来提交、管理和控制任务的执行。以下是几个关键方法:
submit()
用于提交一个任务(Runnable
或 Callable
)并返回 Future
对象,以便检查任务是否完成或获取返回值。
实例
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<?> future = executor.submit(() -> {
System.out.println("Task is running");
});
Future<?> future = executor.submit(() -> {
System.out.println("Task is running");
});
execute()
仅用于提交 Runnable
任务,不返回任何结果。
实例
executor.execute(() -> {
System.out.println("Task executed");
});
System.out.println("Task executed");
});
shutdown()
优雅关闭线程池,不再接受新任务,但会等待已提交的任务完成。
实例
executor.shutdown();
shutdownNow()
立即关闭线程池,尝试中断所有正在执行的任务,并返回未执行的任务列表。
实例
List<Runnable> notExecutedTasks = executor.shutdownNow();
awaitTermination()
等待线程池关闭,直到所有任务完成或超时。
实例
executor.awaitTermination(10, TimeUnit.SECONDS);
如何创建 ExecutorService
Java 提供了 Executors
工具类来创建不同类型的线程池:
newFixedThreadPool(int nThreads)
创建固定大小的线程池,适用于负载稳定的任务。
实例
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
newCachedThreadPool()
创建可缓存的线程池,适用于短生命周期的异步任务。
实例
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
newSingleThreadExecutor()
创建单线程的线程池,适用于顺序执行的任务。
实例
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
newScheduledThreadPool(int corePoolSize)
创建支持定时或周期性任务的线程池。
实例
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
使用示例
提交 Runnable 任务
实例
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> {
System.out.println("Task 1 running");
});
executor.submit(() -> {
System.out.println("Task 2 running");
});
executor.shutdown();
executor.submit(() -> {
System.out.println("Task 1 running");
});
executor.submit(() -> {
System.out.println("Task 2 running");
});
executor.shutdown();
提交 Callable 任务并获取结果
实例
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Task completed";
});
try {
String result = future.get(); // 阻塞直到任务完成
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdown();
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Task completed";
});
try {
String result = future.get(); // 阻塞直到任务完成
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdown();
最佳实践
合理设置线程池大小:
- CPU 密集型任务:
线程数 = CPU 核心数 + 1
- IO 密集型任务:
线程数 = CPU 核心数 * 2
- CPU 密集型任务:
避免内存泄漏:
- 确保调用
shutdown()
或shutdownNow()
关闭线程池。
- 确保调用
处理异常:
- 使用
try-catch
捕获任务中的异常,防止线程意外终止。
- 使用
使用
Future
管理任务:- 通过
Future.get()
获取任务结果或检查任务状态。
- 通过
点我分享笔记