Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作

简介: Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作业务场景:某个业务操作非常耗时,但又必须等这个操作结束后才能进行后续操作

Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作

业务场景:某个业务操作非常耗时,但又必须等这个操作结束后才能进行后续操作

importorg.springframework.util.CollectionUtils;

importjava.util.List;

importjava.util.concurrent.CountDownLatch;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importjava.util.concurrent.TimeUnit;

importjava.util.function.Consumer;

importjava.util.stream.Collectors;

importjava.util.stream.Stream;

/**

* 多线程任务处理工具类

* gzh-JavaNice

*/

publicclassTaskDisposeUtils {

   //并行线程数

   publicstaticfinalintPOOL_SIZE;

   static {

       //判断核心线程数 如果机器的核心线程数大于5则用机器核心线程数

       POOL_SIZE=Integer.max(Runtime.getRuntime().availableProcessors(), 5);

   }

   /**

    * 并行处理,并等待结束

    *

    * @param taskList 任务列表

    * @param consumer 消费者

    * @param <T>

    * @throws InterruptedException

    */

   publicstatic<T>voiddispose(List<T>taskList, Consumer<T>consumer) throwsInterruptedException {

       dispose(true, POOL_SIZE, taskList, consumer);

   }

   /**

    * 并行处理,并等待结束

    *

    * @param moreThread 是否多线程执行

    * @param poolSize   线程池大小

    * @param taskList   任务列表

    * @param consumer   消费者

    * @param <T>

    * @throws InterruptedException

    */

   publicstatic<T>voiddispose(booleanmoreThread, intpoolSize, List<T>taskList, Consumer<T>consumer) throwsInterruptedException {

       if (CollectionUtils.isEmpty(taskList)) {

           return;

       }

       //如果是多线程且核心线程数大于一则进入方法

       if (moreThread&&poolSize>1) {

           poolSize=Math.min(poolSize, taskList.size());

           ExecutorServiceexecutorService=null;

           try {

               //新建一个固定大小的线程池 核心线程数为poolSize

               executorService=Executors.newFixedThreadPool(poolSize);

               //juc工具类 用于让必须所有任务都处理完后才进行下一步

               CountDownLatchcountDownLatch=newCountDownLatch(taskList.size());

               for (Titem : taskList) {

                   executorService.execute(() -> {

                       try {

                           //消费任务

                           consumer.accept(item);

                       } finally {

                           //处理完后减一

                           countDownLatch.countDown();

                       }

                   });

               }

               //在此等待 当countDownLatch变成0后才继续进行下一步

               countDownLatch.await();

           } finally {

               if (executorService!=null) {

                   executorService.shutdown();

               }

           }

       } else {

           for (Titem : taskList) {

               consumer.accept(item);

           }

       }

   }

  publicstaticvoidmain(String[] args) throwsInterruptedException {

       //生成1-10的10个数字,放在list中,相当于10个任务

       List<Integer>list=Stream.iterate(1, a->a+1).limit(10).collect(Collectors.toList());

       JSONObjectobject=newJSONObject();

       object.put("name","sss");

       //启动多线程处理list中的数据,每个任务休眠时间为list中的数值

//        Consumer<Integer> c= item -> {

//            try {

//                long startTime = System.currentTimeMillis();

//                object.put("s",item);

//                TimeUnit.SECONDS.sleep(item);

//                long endTime = System.currentTimeMillis();

//                System.out.println(object.toJSONString());

//                System.out.println(System.currentTimeMillis() + ",任务" + item + "执行完毕,耗时:" + (endTime - startTime));

//            } catch (InterruptedException e) {

//                e.printStackTrace();

//            }

//        };

       TaskDisposeUtils.dispose(list, item-> {

           try {

               longstartTime=System.currentTimeMillis();

               object.put("s",item);

               TimeUnit.SECONDS.sleep(item);

               longendTime=System.currentTimeMillis();

               System.out.println(object.toJSONString());

               System.out.println(System.currentTimeMillis() +",任务"+item+"执行完毕,耗时:"+ (endTime-startTime));

           } catch (InterruptedExceptione) {

               e.printStackTrace();

           }

       });

       //上面所有任务处理完毕完毕之后,程序才能继续

       System.out.println(list+"中的任务都处理完毕!");

   }

}

执行结果

🖊️最后总结

🖲要熟练掌握技巧,一定多多坚持练习:骐骥一跃,不能十步;驽马十驾,功在不舍


目录
相关文章
|
29天前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
3天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
32 20
|
9天前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
1月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
109 17
|
2月前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
79 1
|
2月前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
2月前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
3月前
|
存储 缓存 监控
Java中的线程池深度解析####
本文深入探讨了Java并发编程中的核心组件——线程池,从其基本概念、工作原理、核心参数解析到应用场景与最佳实践,全方位剖析了线程池在提升应用性能、资源管理和任务调度方面的重要作用。通过实例演示和性能对比,揭示合理配置线程池对于构建高效Java应用的关键意义。 ####
|
3月前
|
Java
.如何根据 CPU 核心数设计线程池线程数量
IO 密集型:核心数*2 计算密集型: 核心数+1 为什么加 1?即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保 CPU 的时钟周期不会被浪费。
152 4
|
Java Android开发
WSDL2Java操作指南
1. 安装JDK1.5, 配置系统环境变量:     下载安装JDK后, 设置环境变量:     JAVA_HOME=C:\Program Files\Java\jdk1.5.0_02     Path=%Path%;%JAVA_HOME%\bin(这里的%Path%指你系统已经有的一系列配置)     CLASSPATH=%JAVA_HOME%\lib  2. 下载axis,
1446 0