自定义线程池+countdownlatch

简介: 自定义线程池+countdownlatch

背景


要给前端出个接口,一个数据展示接口,要从好几个表把数据统计出来,所以打算用多线程来查,查完了返回给前端


用到的东西


就需求来说,join可以做到,countdownlatch也可以做到,我喜欢用countdownlatch做,代码看起来简单点,然后涉及到要开启多线程,所以还是自己来维护一个线程池来用。


代码


线程池部分


@Configuration
@EnableAsync //开启多线程
public class ThreadPoolConfig {
    private static final long serialVersionUID = -4778941758120026886L;
    /** 线程池维护线程的最少数量 */
    private int minPoolSize = 4;
    /** 线程池维护线程的最大数量 */
    private int maxPoolSize = 16;
    /** 线程池维护线程所允许的空闲时间 */
    private int idleSeconds = 1800;
    /** 线程池所使用的缓冲队列 */
    private int queueBlockSize = 30;
    private ThreadPoolExecutor executor;
    @Bean("taskExecutor")
    public Executor asyncServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(minPoolSize);
        // 设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueBlockSize);
        // 设置线程空闲时间,当超过核心线程之外的线程在空闲到达之后会被销毁(秒)
        executor.setKeepAliveSeconds(idleSeconds);
        // 设置默认线程名称
        executor.setThreadNamePrefix("ThreadExcutor");
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
    public ThreadPoolConfig() {
        this.executor = new ThreadPoolExecutor(minPoolSize, maxPoolSize, idleSeconds,
                TimeUnit.SECONDS, /* 时间单位,秒 */
                new ArrayBlockingQueue<Runnable>(queueBlockSize),
                new ThreadPoolExecutor.CallerRunsPolicy()); /* 重试添加当前加入失败的任务 */
    }
    public void execute(Runnable task) {
        executor.execute(task);
    }
    public <T> Future<T> submit(Callable<T> task){
        return executor.submit(task);
    }
 }


countdownlatch代码


public QuotaInfoVo getQuotaInfo() {
        StopWatch sw = new StopWatch();
        sw.start();
        QuotaInfoVo info=new QuotaInfoVo();
        final CountDownLatch latch = new CountDownLatch(4);
        String id=tmpFcrmId; //这个是从配置文件拿的
        if (StringUtils.isEmpty(id)){
            throw new ServiceException(ResultCode.ERROR);
        }
        taskExecutor.execute(new Task1(info,latch,id));
        taskExecutor.execute(new Task2(info,latch,id));
        taskExecutor.execute(new Task3(info,latch,id));
        taskExecutor.execute(new Task4(info,latch,id));
        try {
            //主线程等待所有统计指标执行完毕
            latch.await(5, TimeUnit.SECONDS);
            //latch.await();
            sw.stop();
            log.info("getQuotaInfo finish ,total time is {}",sw.getTotalTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return info;
    }


然后给一个task的例子


private class Task1 implements Runnable{
        private QuotaInfoVo quotaInfoVo;
        private CountDownLatch countDownLatch;
        private String id;
        public OrderCount(QuotaInfoVo quotaInfoVo,CountDownLatch countDownLatch,String id){
            this.quotaInfoVo=quotaInfoVo;
            this.countDownLatch=countDownLatch;
            this.id=id;
        }
        @Override
        public void run() {
      //这里写自己的逻辑处理
      //处理完了记得countDown
            countDownLatch.countDown();
        }
    }


注意事项


最主要需要注意的就是主线程的这个部分:


try {
            //主线程等待所有统计指标执行完毕
            latch.await(5, TimeUnit.SECONDS);
            //latch.await();
            sw.stop();
            log.info("getQuotaInfo finish ,total time is {}",sw.getTotalTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


latch.await如果不加等待时间的话,当某个线程执行出错,卡在那里,那么主线程会一直等待,这肯定是我们不想看到的,所以await一定要加等待时间。

目录
相关文章
|
2月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
202 0
|
7月前
|
Java 数据库连接 调度
面试题:用过线程池吗?如何自定义线程池?线程池的参数?
字节跳动面试题:用过线程池吗?如何自定义线程池?线程池的参数?
97 0
|
5月前
|
Java 开发者
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
59 0
|
2月前
|
Java C++
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
35 0
|
4月前
|
存储 Java 开发者
HashMap线程安全问题大揭秘:ConcurrentHashMap、自定义同步,一文让你彻底解锁!
【8月更文挑战第24天】HashMap是Java集合框架中不可或缺的一部分,以其高效的键值对存储和快速访问能力广受开发者欢迎。本文深入探讨了HashMap在JDK 1.8后的底层结构——数组+链表+红黑树混合模式,这种设计既利用了数组的快速定位优势,又通过链表和红黑树有效解决了哈希冲突问题。数组作为基石,每个元素包含一个Node节点,通过next指针形成链表;当链表长度过长时,采用红黑树进行优化,显著提升性能。此外,还介绍了HashMap的扩容机制,确保即使在数据量增大时也能保持高效运作。通过示例代码展示如何使用HashMap进行基本操作,帮助理解其实现原理及应用场景。
61 1
|
5月前
|
Java Spring 容器
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
244 3
|
4月前
|
Java UED
基于SpringBoot自定义线程池实现多线程执行方法,以及多线程之间的协调和同步
这篇文章介绍了在SpringBoot项目中如何自定义线程池来实现多线程执行方法,并探讨了多线程之间的协调和同步问题,提供了相关的示例代码。
1103 0
|
5月前
|
Java
不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutor
不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutor
|
6月前
|
Java
Runnable+CountDownLatch多线程的等待和通知
Runnable+CountDownLatch多线程的等待和通知
|
6月前
|
API
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
39 1