目录
线程池简介
线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如Tomcat。
线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。
线程池有如下的优势:
- 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
- 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
- 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。
线程池的使用
创建线程池
ThreadPoolExecutor—推荐使用
利用ThreadPoolExecutor提供的构造方法创建线程池

主要看参数最全的构造方法,其他构造方法最终还是会调用该改造方法

线程池的核心参数
corePoolSize:核心线程数,线程池初始化时默认是没有线程的,当任务来临时才开始创建线程去执行任务。
maximumPoolSize:最大线程数,当核心线程数已满,且队列已满时,如果池子里的工作线程数小于maximumPoolSize,则会创建非核心线程执行任务。
keepAliveTime:非核心线程数的空闲时间超过keepAliveTime就会被自动终止回收掉,但在corePoolSize=maximumPoolSize时,该值无效,因为不存在非核心线程。
unit:keepAliveTime的时间单位。
workQueue:用于保存线程任务的队列,主要分为无界、有界、同步移交等队列,当池子里的工作线程数大于corePoolSize,就会将新进来的线程任务放入队列中。
- ArrayBlockingQueue(有界队列):队列长度有限,当队列满了就需要创建非核心线程执行任务,如果最大线程数已满,则执行拒绝策略
- LinkedBlockingQueue(无界队列):队列长度无限,当任务处理速度跟不上任务创建速度,可能会导致内存占用过多或OOM
- SynchronousQueue(同步队列):队列不作为任务的缓冲处理,队列长度为0。
threadFactory:
- 创建线程的工厂接口,默认使用Executors.defaultThreadFactory()
- 另外可以实现ThreadFactory接口,自定义线程工厂
handler:线程池无法继续接收任务时(workQueue已满和maximumPoolSize已满)的拒绝策略
- AbortPolicy:默认拒绝策略,中断抛出RejectedExecutionException异常
- CallerRunsPolicy:让提交任务的主线程来执行任务
- DiscardOldestPolicy:丢弃在队列中存在时间最久的任务,重复执行
- DiscardPolicy:丢弃任务,不进行任何通知
- 另外可以实现RejectedExecutionHandler接口,自定义拒绝策略

以下是一个使用ThreadPoolExecutor创建线程池的示例:
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 自定义实现线程工厂
*/
public class CustomThreadFactory implements ThreadFactory {
private final AtomicInteger i = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
// 创建线程
Thread thread = new Thread(r);
// 设置线程名称
thread.setName("线程" + i.getAndIncrement());
return thread;
}
}
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
/**
* 线程池例子
*/
@Slf4j
public class ThreadPoolExample2 {
public static void main(String[] args) {
// 线程池的核心线程数
int corePoolSize = 3;
// 线程池的最大线程数
int maximumPoolSize = 5;
// 线程池的任务队列
ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3);
// 线程池中工作线程(默认是非核心线程)保持空闲的时间
long keepAliveTime = 60L;
// 时间单位
TimeUnit unit = TimeUnit.SECONDS;
// 自定义线程工厂,不写会使用默认工厂
ThreadFactory threadFactory = new CustomThreadFactory();
// 线程池的拒绝策略
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
// 提交任务到线程池,最大线程5,队列3,所以最大支持8个线程,大于8会抛出异常,
// 核心线程3,队列3,所以当线程为6的时候只会开3个线程,超过6才会开启新的线程,直到达到最大线程5
for (int i = 0; i < 8; i++) {
final int taskId = i;
executor.execute(() -> {
try {
// 模拟业务处理时间
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("Task " + taskId + " is running by " + Thread.currentThread().getName());
});
}
// 关闭线程池,不再接受新任务
executor.shutdown();
// 关闭线程池后再提交新任务会报错
// executor.execute(new Runnable() {
// @Override
// public void run() {
// System.out.println("新任务");
// }
// });
try {
// 等待所有任务完成,阻塞当前线程,直到所有已提交的任务执行完毕,或者达到指定的等待时间
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
// 如果超时后任务仍未完成,则强制关闭线程池
executor.shutdownNow();
}
} catch (InterruptedException e) {
// 如果等待过程中被中断,也强制关闭线程池
executor.shutdownNow();
}
System.out.println("All tasks are done or interrupted.");
}
}
Executors—不推荐使用
Executors提供了各种线程池类型创建的静态方法,如常见的newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool、newSingleThreadScheduledExecutor。


以下是一个使用Java中的ExecutorService和Executors创建线程池的简单示例:
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 线程池例子
*/
@Slf4j
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("Task " + taskId + " is running by " + Thread.currentThread().getName());
});
}
// 关闭线程池
executor.shutdown();
while (!executor.isTerminated()) {
// 等待所有任务完成
}
System.out.println("All tasks are done.");
}
}
但不提倡使用该种方式创建线程池,在阿里巴巴JAVA开发手册,对于线程池创建要求:

提交任务
线程池提交任务有两种方法:
- 无返回值的任务使用 public void execute(Runnable command) 方法提交;
- 有返回值的任务使用:
- Future submit(Runnable task) : 提交Runnable任务
- Future submit(Runnable task, T result): 提交Runnable任务并指定执行结果
- Future submit(Callable task) : 提交Callable任务
代码示例
import java.util.concurrent.*;
public class ThreadDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建任务
Task task1 = new Task();
Task task2 = new Task();
Task task3 = new Task();
// 创建一个只要一个线程的线程池
ExecutorService threadpool = Executors.newSingleThreadExecutor();
threadpool.submit(task1);
threadpool.submit(task2);
Future<String> future = threadpool.submit(task3, "执行完成");
System.out.println("future:" + future.get());
Callable callable = new Callable() {
@Override
public Object call() throws Exception {
return "执行完成";
}
};
Future future2 = threadpool.submit(callable);
System.out.println("future2:" + future2.get());
}
}
class Task implements Runnable {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName());
}
}
如何执行批量任务
# 执行批量任务,返回它们的执行结果
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
# 执行批量任务,返回指定时间内完成的执行结果,取消未完成的任务
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
# 执行批量任务,返回最先完成的执行结果
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
# 执行批量任务,返回指定时间内最先完成的执行结果,取消未完成的任务
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
代码示例
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* 线程池批量提交任务示例
*/
public class InvokeAllDemo {
public static void main(String[] args) {
List<Task> tasks = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
tasks.add(new Task(i));
}
// 创建线程池
ExecutorService threadpool = Executors.newFixedThreadPool(5);
try {
// 批量提交任务
List<Future<Integer>> futures = threadpool.invokeAll(tasks);
for (Future<Integer> future : futures) {


9万+

被折叠的 条评论
为什么被折叠?



