寒假打卡04_1月16日
Java 线程池的使用——ExecutorService 和 ThreadPoolExecutor 解析
在多线程编程中,线程池是一种非常重要的工具。它能够有效地管理和复用线程资源,从而提高程序的性能和响应速度。在本篇文章中,我们将详细探讨 Java 中的线程池概念,并介绍 ExecutorService
和 ThreadPoolExecutor
的使用方法。
线程池的概念
线程池是一种线程管理机制,它预先创建了一定数量的线程,并将其放入池中。通过这种方式,程序可以重复利用这些线程,而不需要频繁地创建和销毁线程,从而减少了系统资源的消耗。
使用线程池的好处包括:
- 降低线程创建和销毁的开销
- 提高响应速度
- 有效控制并发线程的数量,避免资源过度消耗
Executor 框架
Java 从 java.util.concurrent
包开始引入了 Executor
框架,它提供了一套用于并发编程的标准 API。其中,ExecutorService
和 ThreadPoolExecutor
是两个非常重要的接口和类。
ExecutorService
ExecutorService
是一个高级接口,定义了一组方法来管理终止和跟踪异步任务的执行。我们可以通过调用 Executors
工具类的静态方法来创建 ExecutorService
实例,例如 newFixedThreadPool
、newCachedThreadPool
、newSingleThreadExecutor
等。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceDemo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + " is running");
});
}
executorService.shutdown();
}
}
在上述代码中,我们创建了一个固定大小为 3 的线程池,并提交了 5 个任务。线程池中的线程将依次执行这些任务。
ThreadPoolExecutor
ThreadPoolExecutor
是 ExecutorService
的一个实现类,它提供了更为灵活和强大的线程池功能。我们可以通过其构造方法来创建定制化的线程池。
import java.util.concurrent.*;
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS, // keepAliveTime unit
new ArrayBlockingQueue<>(2), // workQueue
new ThreadPoolExecutor.AbortPolicy() // handler
);
for (int i = 0; i < 6; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " is running");
});
}
executor.shutdown();
}
}
在上述代码中,我们创建了一个 ThreadPoolExecutor
实例,并设置了核心线程数为 2、最大线程数为 4、线程空闲时间为 60 秒、工作队列为 ArrayBlockingQueue
、拒绝策略为 AbortPolicy
。我们提交了 6 个任务,线程池中的线程将依次执行这些任务。
线程池的拒绝策略
当线程池的工作队列已满且没有空闲线程时,线程池需要采取一定的策略来处理新提交的任务。ThreadPoolExecutor
提供了以下几种拒绝策略:
AbortPolicy
:直接抛出RejectedExecutionException
异常,默认策略CallerRunsPolicy
:由调用线程执行该任务DiscardPolicy
:直接丢弃任务,不予处理DiscardOldestPolicy
:丢弃最旧的未处理任务,然后重新提交新任务
我们可以在创建 ThreadPoolExecutor
时通过构造方法的 handler
参数来指定拒绝策略。
示例代码
以下是一个使用 ExecutorService
和 ThreadPoolExecutor
的示例代码,展示了如何创建和管理线程池:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
submitTasks(fixedThreadPool);
// 创建一个自定义的线程池
ThreadPoolExecutor customThreadPool = new ThreadPoolExecutor(
2, 4, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), new ThreadPoolExecutor.CallerRunsPolicy()
);
submitTasks(customThreadPool);
}
private static void submitTasks(ExecutorService executorService) {
for (int i = 0; i < 5; i++) {
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + " is executing task");
});
}
executorService.shutdown();
}
}
在上述代码中,我们创建了一个固定大小的线程池和一个自定义的线程池,并向它们提交了任务。线程池中的线程将依次执行这些任务。
总结
线程池是多线程编程中非常重要的工具,它能够有效地管理和复用线程资源,从而提高程序的性能和响应速度。Java 提供了 ExecutorService
和 ThreadPoolExecutor
等类来实现线程池功能。通过使用这些类,我们可以轻松地创建和管理线程池,确保程序的高效运行。
希望通过本篇文章,大家对 Java 线程池的使用有了更深入的了解。在接下来的文章中,我们将继续探讨更多关于 Java 多线程的知识点,敬请期待!