再看线程池

72 阅读3分钟

JDK线程池解析

脑子一直没有一个体系,今天有时间来总结一下

Java提供了一个Executors工厂类,它提供了一些静态方法来创建不同类型的线程池:

newFixedThreadPool:返回固定长度的线程池,线程池中的线程数量是固定的。

阿里规范:使用Executors创建的线程池通常不建议用于生产环境,因为它们的默认配置可能不适合所有的应用场景。例如,newCachedThreadPool()可能会创建大量的线程,导致资源耗尽。

     @Test
     public void testThread() throws ExecutionException, InterruptedException {
         ExecutorService executorService = Executors.newFixedThreadPool(10);
         Future<Integer> future = executorService.submit(() -> {
             System.out.println("开始线程工作");
             return 10;
         });
         System.out.println(future.get());
     }

解析:Executors是一个工厂,里面封装了不同类型的线程池,帮我们做了创建了ThreadPoolExecutor

     public static ExecutorService newFixedThreadPool(int nThreads) {
         return new ThreadPoolExecutor(nThreads, nThreads,
                                       0L, TimeUnit.MILLISECONDS,
                                       new LinkedBlockingQueue<Runnable>());
     }

ThreadPoolExecutor是什么?看源码是继承了AbstractExecutorService

这个抽象的AbstractExecutorService是实现了ExecutorService

所以ThreadPoolExecutor是间接实现了ExecutorService

ExecutorService呢?这个接口是继承了顶层接口Executor,顶层接口只是定义了核心功能,而ExecutorService这个接口是对顶层接口进行了扩展,也是一个接口

 ThreadPoolExecutor extends AbstractExecutorService
 public abstract class AbstractExecutorService implements ExecutorService
 public interface ExecutorService extends Executor
 public interface Executor {
 ​
     /**
      * Executes the given command at some time in the future.  The command
      * may execute in a new thread, in a pooled thread, or in the calling
      * thread, at the discretion of the {@code Executor} implementation.
      *
      * @param command the runnable task
      * @throws RejectedExecutionException if this task cannot be
      * accepted for execution
      * @throws NullPointerException if command is null
      */
     void execute(Runnable command);
 }

总结:ThreadPoolExecutorThreadPoolExecutor的一个具体实现类,提供了一个能够管理和执行异步任务的线程池。ThreadPoolExecutor允许你配置线程池的大小、任务的执行策略、任务队列以及任务拒绝策略等

有点乱,来跟着我思路捋一遍:首先Executor是一个顶层接口,然后它下面的ExecutorService接口继承了该接口,对其功能进行了扩展,然后抽象类AbstractExecutorService实现了该接口,然后ThreadPoolExecutor继承了该抽象类,相当于间接实现了ExecutorService

思考:源码中为什么会有public abstract class AbstractExecutorService implements ExecutorService呢?直接让ThreadPoolExecutor实现ExecutorService接口不行吗?

其实ThreadPoolExecutor就是一个执行器,它还有其他同类型的执行器(ScheduledThreadPoolExecutorForkJoinPool),所以abstractExecutorService作为一个中间层,使得ThreadPoolExecutor和其他执行器服务实现能够更加专注于它们独特的功能,同时保持代码的清晰和可维护性。

Spring提供的线程池

     @Bean(name = "taskExecutor")
     public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
         ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
         pool.setKeepAliveSeconds(keepAliveSeconds);
         //核心线程池数
         pool.setCorePoolSize(corePoolSize);
         // 最大线程
         pool.setMaxPoolSize(maxPoolSize);
         //队列容量
         pool.setQueueCapacity(queueCapacity);
         //队列满,线程被拒绝执行策略
         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         return pool;
     }

公司中的使用,自定义的线程池参数

threadPoolTaskExecutor是实现了TaskExecutor接口,与ThreadPoolExecutor类型都是一个执行器

使用类似:使用execute或者submit执行,异步配合:

image.png

CompletableFuture.allOf 方法用于同步等待一组异步操作的完成,但它本身并不返回这些操作的结果

join 来获取每个 CompletableFuture 对象的结果

 //同步等待一组异步操作的完成
 CompletableFuture<Void> result1 = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
 //来获取每个 `CompletableFuture` 对象的结果
 CompletableFuture<List<FilterData>> listCompletableFuture1 = result1.thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()));