创建线程池对象 :
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,时间单位,任务队列,创建线程工厂,任务的拒绝策略);
线程池处理流程
-
线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作 线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
-
线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这 个工作队列里。如果工作队列满了,则进入下个流程。
-
线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程 来执行任务。如果已经满了,则交给饱和策略来处理这个任务
提交方法
可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。 submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个 future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方 法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线 程一段时间后立即返回,这时候有可能任务没有执行完。
execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。
线程池-参数详解
任务队列:
ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原 则对元素进行排序。
LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通 常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用 移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue,静态工 厂方法Executors.newCachedThreadPool使用了这个队列。
PriorityBlockingQueue:一个具有优先级的无限阻塞队列
线程池-任务拒绝策略
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。是默认的策略。
ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常 这是不推荐的做法。
ThreadPoolExecutor.DiscardOldestPolicy: 抛弃队列中等待最久的任务 然后把当前任务加入队列中。
ThreadPoolExecutor.CallerRunsPolicy: 调用任务的run()方法绕过线程池直接执行。
明确线程池最多可执行的任务数 = 队列容量 + 最大线程数
代码示例:
// 创建一个ArrayList来存放异步计算结果
final List<GzltjRespVO> gzltjRespVOS = Collections.synchronizedList(new ArrayList<>());
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
10, // 线程空闲超时时间(单位:秒)
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(20), // 工作队列大小
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务到线程池
userRoleIdListByRoleIds.forEach(roleId -> {
threadPoolExecutor.submit(() -> {
log.info(Thread.currentThread().getName() + "---" + roleId);
GzltjRespVO gzltjRespVO = calculateGzltjRespVO(roleId, kssj, jzsj);
synchronized (gzltjRespVOS) {
gzltjRespVOS.add(gzltjRespVO);
}
});
});
// 等待所有任务完成
threadPoolExecutor.shutdown();
try {
threadPoolExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted while waiting for task completion", e);
}
gzltjRespVOS.sort(Comparator.comparing(GzltjRespVO::getName).reversed());
return success(gzltjRespVOS);
}