一、简介
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
丢弃队列中最前面的任务,然后重新尝试执行任务