zoukankan      html  css  js  c++  java
  • java 多线程:线程池的使用Executors~ExecutorService; newCachedThreadPool;newFixedThreadPool(int threadNum);ScheduledExecutorService

    1,为什么要使用线程池:Executors

    系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互。在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。
    线程池在系统启动时即创建大量空闲的线程,程序将Runnable对象或Callable对象传给线程池,线程池就会启动1个空闲的线程来执行它们的run()或者call()方法run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象或者Callable对象的run()或者call()方法
     

    2,线程池的基本使用:

    在Java5之前开发者要实现线程池必须手动去实现。但是在Java5之后,提供了一个Executors工厂类来生产线程池,这个类提供了很多工厂方法,我们会逐一的去写。
    使用线程池的流程如下:
    • (1),调用Executors静态方法newXXXX获取ExecutorService对象,该对象代表一个线程池
    • (2),创建Runnable实例或Callable实例,作为线程运行任务。
    • (3),调用ExecutorService对象的submit()方法来提交Runnable或Callable实例。
    • (4),当不想提交任务时,调用ExecutorService 对象 shutdown()方法来关闭线程池

    示例:newCachedThreadPool

    import java.util.concurrent.ExecutorService;
            import java.util.concurrent.Executors;
    
    /**
     * @ClassName ExecutorsThreadPoolTest
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/26.
     */
    public class ExecutorsThreadPoolTest {
        public static void main(String[] args) {
            Runnable r = () ->{
                String tName = Thread.currentThread().getName();
                System.out.println(tName + "运行中...");
                try {
                    Thread.sleep(1000);
                    System.out.println(tName + "运行结束!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            ExecutorService threadPool = Executors.newCachedThreadPool();
            for (int i=0; i<10; i++) {
                threadPool.submit(r);
            }
            /**
             * 如果不关闭线程池。则持续等待提交新的线程
             */
            threadPool.shutdown();  //关闭线程池就无法再次submit;已submit的线程运行结束后会退出
        }
    }

    3、创建线程池的静态方法

    • 1,ExecutorService newCachedThreadPool():创建一个具有缓存功能的线程池,系统会根据需要创建线程,这些创建的线程会缓存在线程池中,以后,如果它是空闲,可以被复用。
    • 2,ExecutorService newFixedThreadPool(int threadNum):创建一个可重用的,具有固定线程数量的线程池。
    • 3,ExecutorService newSingleThreadExecutor():创建一个只有单线程的线程池,它相 于调用 newFixedThreadPool()方法时传入参数为1

    测试用例:newFixedThreadPool、ewSingleThreadExecutor

    import java.util.concurrent.Executor;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @ClassName ExecutorsFixedThreadPool
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/27.
     */
    public class ExecutorsFixedThreadPool {
        public static void main(String[] args) {
            Runnable runnable = () -> {
                String tName = Thread.currentThread().getName();
                System.out.println(tName + "开始运行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(tName + "33[31;1m运行结束33[0m");
            };
    //        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);  //固定线程数量的线程池
            ExecutorService fixedThreadPool = Executors.newSingleThreadExecutor();  //只有一个线程的线程池
            for (int i=0; i<10; i++){
                fixedThreadPool.submit(runnable,"te");
            }
            fixedThreadPool.shutdown();
    
        }
    }

    3,线程池延迟任务和定时任务ScheduledExecutorService类

    • 1,newScheduledThreadPool(int corePooISize): 创建具有指定线程数的线程池,它可以在指定延迟后执行线程任务 corePoolSize 指池中所保存的线程数,即使线程是空闲的也被保存在线程池
      执行任务方法:
      等待指定时间后执行一次:schedule(r,5, TimeUnit.SECONDS) ,r为Runnable或Callable对象后面   :
      等待指定时间后执行,然后周期性执行
      scheduleAtFixedRate(r,5,1,TimeUnit.SECONDS)
    • 2,newSingleThreadScheduledExecutor(): 创建只一个线程的线程池,它可以在指定延迟后执行线程任务
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @ClassName ExecutorsScheduledThreadPoolTest
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/27.
     */
    public class ExecutorsScheduledThreadPoolTest {
        public static void main(String[] args) {
            Runnable r = () -> {
                String tName = Thread.currentThread().getName();
                System.out.println(tName + "运行中");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(tName + "运行结束");
            };
            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
            /**
             * schedule 任务已提交到线程池,5S后执行
             */
    //        executorService.schedule(r,5, TimeUnit.SECONDS); //任务已提交到线程池,5S后执行
            /**
             * scheduleAtFixedRate
             * 任务等到时间才提交,周期性提交、不能shutdown,shutdown后无法提交了
             * 注:如果下一次执行时,上次自行的还没结束,则这次取消执行
             */
            executorService.scheduleAtFixedRate(r,5,1,TimeUnit.SECONDS);
    //        executorService.shutdown();
        }
    }

    4,给定并行级别:

    • 1,ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争
    • 2,ExecutorService newWorkStealingPool(): 该方法是前面方法的简化版本 如果前机器有4个CPU,则目标并行级别被设置为4
    • 这两个方法是Java8新增的,这两个方法可充分利用多 CPU 并行的能力 这两个方法生成的 work stealing 池,都相于后台线程池,如果所有的前台线程都死亡了workstealing 池中的线程会自动死亡。
    这两个方法是Java8新增的,这两个方法可充分利用多 CPU 并行的能力 这两个方法生成的 work stealing 池,都相于后台线程池,如果所有的前台线程都死亡了workstealing 池中的线程会自动死亡。
     
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @ClassName ExecutorsWorkStealingPoolTest
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/27.
     */
    public class ExecutorsWorkStealingPoolTest {
        public static void main(String[] args) throws InterruptedException {
            Runnable r = () -> {
                String tName = Thread.currentThread().getName();
                try {
                    System.out.println(tName + "开始运行");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(tName + "运行结束");
            };
            /**
             * 创建支持多核CPU并行的线程池
             */
            ExecutorService executorService = Executors.newWorkStealingPool(); //译文:Stealing 窃取
            for (int i=0; i<10; i++){
                executorService.submit(r);
            }
            System.out.println(Runtime.getRuntime().availableProcessors()); //CPU核心数
            Thread.sleep(3000);
        }
    }

     
  • 相关阅读:
    JavaScript高级程序设计读书笔记(二)变量 作用域和内存
    JavaScript高级程序设计读书笔记(一)基础概念
    angular6 + ng-zorro鹿途后台管理系统(三)项目升级改造 01 升级ng-zorro-antd到1.8+
    angular6 + ng-zorro鹿途后台管理系统(三)环境变量配置
    angular6 + ng-zorro鹿途后台管理系统(二)项目结构规划
    angular6 + ng-zorro鹿途后台管理系统(一)
    web-view——微信小程序嵌入H5
    JS知识整理随笔(8) BOM
    JS知识整理随笔(7) DOM事件
    基础信息论 (复习)
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/14706965.html
Copyright © 2011-2022 走看看