zoukankan      html  css  js  c++  java
  • Java多线程之ThreadPoolTaskExecutor用法

    一、简介

    ThreadPoolTaskExecutor线程是Spring的线程池,其底层是依据JDK线程池ThreadPoolExecutor来实现的。

    二、参数介绍

    corePoolSize:线程池维护线程最小的数量,默认为1
    maxPoolSize:线程池维护线程最大数量,默认为Integer.MAX_VALUE
    keepAliveSeconds:(maxPoolSize-corePoolSize)部分线程空闲最大存活时间,默认存活时间是60s
    queueCapacity:阻塞任务队列的大小,默认为Integer.MAX_VALUE,默认使用LinkedBlockingQueue
    allowCoreThreadTimeOut:设置为true的话,keepAliveSeconds参数设置的有效时间对corePoolSize线程也有效,默认是flase
    threadFactory::用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线程设置有意义的名字
    rejectedExecutionHandler:拒绝策略,当队列workQueue和线程池maxPoolSize都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。

    三、拒绝策略

    拒绝策略有以下四种,默认情况下是AbortPolicy,也可根据实际业务需求类实现RejectedExecutionHandler接口实现自己的处理策略
    1.AbortPolicy:丢弃任务,并且抛出RejectedExecutionException异常;
    2.DiscardPolicy:丢弃任务,不处理,不抛出异常;
    3.CallerRunsPolicy:直接在execute方法的调用线程中运行被拒绝的任务;
    4.DiscardOldestPolicy:丢弃队列中最前面的任务,然后重新尝试执行任务。

    四、处理流程

    1.查看核心线程池是否已满,不满就创建一条线程执行任务,否则执行第二步。
    2.查看任务队列是否已满,不满就将任务存储在任务队列中,否则执行第三步。
    3.查看线程池是否已满,即就是是否达到最大线程池数,不满就创建一条线程执行任务,否则就按照策略处理无法执行的任务。

    四、代码示例

    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    import java.util.concurrent.ThreadPoolExecutor;
        /**
         * ThreadPoolTaskExecutor用法:
         * corePoolSize:线程池维护线程最小的数量,默认为1
         * maxPoolSize:线程池维护线程最大数量,默认为Integer.MAX_VALUE
         * keepAliveSeconds:(maxPoolSize-corePoolSize)部分线程空闲最大存活时间,默认存活时间是60s
         * queueCapacity:阻塞任务队列的大小,默认为Integer.MAX_VALUE,默认使用LinkedBlockingQueue
         * allowCoreThreadTimeOut:设置为true的话,keepAliveSeconds参数设置的有效时间对corePoolSize线程也有效,默认是flase
         * threadFactory::用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线程设置有意义的名字
         * rejectedExecutionHandler:拒绝策略,当队列workQueue和线程池maxPoolSize都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常,有以下四种策略,当然也可以根据实际业务需求类实现RejectedExecutionHandler接口实现自己的处理策略
         * 1.AbortPolicy:丢弃任务,并且抛出RejectedExecutionException异常
         * 2.DiscardPolicy:丢弃任务,不处理,不抛出异常
         * 3.CallerRunsPolicy:直接在execute方法的调用线程中运行被拒绝的任务
         * 4.DiscardOldestPolicy:丢弃队列中最前面的任务,然后重新尝试执行任务
         */
        @Test()
        public void _03_test() throws Exception {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(3); //核心池大小
            executor.setMaxPoolSize(10); //最大线程数
            executor.setQueueCapacity(10); //队列程度
            executor.setKeepAliveSeconds(60); //线程空闲时间
            executor.setThreadNamePrefix("子线程-");//线程前缀名称
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); //配置拒绝策略
            executor.initialize(); //初始化
    
            Runnable task = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + " 工作开始!");
                        Thread.sleep((long) (Math.random() * 2000));
    //                    Thread.sleep(3000);
                        System.out.println(Thread.currentThread().getName() + " 工作结束!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            for (int i = 0; i < 5; i++) {
                executor.execute(task);
            }
            int n = Runtime.getRuntime().availableProcessors();//获取到服务器的cpu内核
            log.info("服务器的cpu内核:{}", n);
    
            Thread.sleep(5000);
            System.out.println("主线程工作结束!");
            executor.shutdown();
        }

     运行结果:

    03-02 14:39:00 Initializing ExecutorService 
    子线程-1 工作开始!
    子线程-3 工作开始!
    子线程-2 工作开始!
    03-02 14:39:00 服务器的cpu内核:8 
    子线程-3 工作结束!
    子线程-3 工作开始!
    子线程-2 工作结束!
    子线程-2 工作开始!
    子线程-2 工作结束!
    子线程-1 工作结束!
    子线程-3 工作结束!
    主线程工作结束!
    03-02 14:39:05 Shutting down ExecutorService 

    五、多线程同步工具用法

    /**
         * 多线程同步工具用法(单独方法)
         * ThreadPoolTaskExecutor和CountDownLatch结合用法
         */
        @Test
        public void _05_test() throws Exception {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(3); //核心池大小
            executor.setMaxPoolSize(10); //最大线程数
            executor.setQueueCapacity(10); //队列程度
            executor.setThreadNamePrefix("子线程-");//线程前缀名称
            executor.initialize(); //初始化
    
            int count = 5; // 任务数量
            CountDownLatch countDownLatch = new CountDownLatch(count); // 同步工具
            for (int i = 0; i < count; i++) {
                executor.execute(() -> task(countDownLatch));
            }
            System.out.println("等待子线程完成...");
            countDownLatch.await();
            System.out.println("主线程工作结束!");
            executor.shutdown();
        }
    
        private void task(CountDownLatch countDownLatch) {
            try {
                System.out.println(Thread.currentThread().getName() + " 工作开始!");
                Thread.sleep((long) (Math.random() * 2000));
                System.out.println(Thread.currentThread().getName() + " 工作结束!");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    运行结果:

    03-02 14:59:41 Initializing ExecutorService 
    子线程-1 工作开始!
    子线程-2 工作开始!
    子线程-3 工作开始!
    等待子线程完成
    子线程-2 工作结束!
    子线程-2 工作开始!
    子线程-3 工作结束!
    子线程-3 工作开始!
    子线程-2 工作结束!
    子线程-3 工作结束!
    子线程-1 工作结束!
    主线程工作结束!
    03-02 14:59:42 Shutting down ExecutorService 
    丢弃队列中最前面的任务,然后重新尝试执行任务
  • 相关阅读:
    oracle 导入数据时提示只有 DBA 才能导入由其他 DBA 导出的文件
    oracle 常用语句
    android udp 无法收到数据 (模拟器中)
    android DatagramSocket send 发送数据出错
    AtCoder ABC 128E Roadwork
    AtCoder ABC 128D equeue
    AtCoder ABC 127F Absolute Minima
    AtCoder ABC 127E Cell Distance
    CodeForces 1166E The LCMs Must be Large
    CodeForces 1166D Cute Sequences
  • 原文地址:https://www.cnblogs.com/gongxr/p/14468802.html
Copyright © 2011-2022 走看看