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 
    丢弃队列中最前面的任务,然后重新尝试执行任务
  • 相关阅读:
    LeetCode 55
    LeetCode 337
    LeetCode 287
    LeetCode 274
    LeetCode 278
    LeetCode 264
    LeetCode 189
    LeetCode 206
    LeetCode 142
    LeetCode 88
  • 原文地址:https://www.cnblogs.com/gongxr/p/14468802.html
Copyright © 2011-2022 走看看