一、概述

Spring通过ThreadPoolTaskExecutor实现线程池技术,它是使用jdk中的Java.util.concurrent.ThreadPoolExecutor进行实现。

1.1、xml方式配置

  1. <!-- Spring线程池 -->
  2. <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  3. <!-- 核心线程数 -->
  4. <property name="corePoolSize" value="5" />
  5. <!-- 线程池维护线程的最大数量 -->
  6. <property name="maxPoolSize" value="10" />
  7. <!-- 允许的空闲时间, 默认60秒 -->
  8. <property name="keepAliveSeconds" value="60" />
  9. <!-- 任务队列 -->
  10. <property name="queueCapacity" value="50" />
  11. <!-- 线程超过空闲时间限制,均会退出直到线程数量为0 -->
  12. <property name="allowCoreThreadTimeOut" value="true"/>
  13. <!-- 对拒绝task的处理策略 -->
  14. <property name="rejectedExecutionHandler">
  15. <bean class="java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy" />
  16. </property>
  17. </bean>

java代码

  1. //帮我们创建容器
  2. @RunWith(SpringJUnit4ClassRunner.class)
  3. //指定创建容器时使用哪个配置文件
  4. @ContextConfiguration("classpath:applicationContext.xml")
  5. public class SpringThreadPoolExecutorTest {
  6.  
  7. @Autowired
  8. private ThreadPoolTaskExecutor taskExecutor;
  9.  
  10. @Test
  11. public void newFixedThreadPoolTestSubmit() throws Exception {
  12. List<Future<?>> list=new ArrayList<>();
  13. for (int i = 0; i < 20; i++) {
  14. Future<?> submit = taskExecutor.submit(new DataTask("ssss" + i));
  15. list.add(submit);
  16. }
  17. for (Future<?> future : list) {
  18. future.get();
  19. }
  20. }
  21.  
  22. class DataTask implements Runnable {
  23. private String a;
  24.  
  25. public DataTask(String a) {
  26. this.a = a;
  27. }
  28.  
  29. @Override
  30. public void run() {
  31. try {
  32. Thread.sleep(1000);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. System.out.println("-------"+ LocalDateTime.now()+a);
  37. }
  38. }
  39. }

输出

  1. -------2019-08-06T21:23:18.105ssss0
  2. -------2019-08-06T21:23:18.105ssss3
  3. -------2019-08-06T21:23:18.105ssss1
  4. -------2019-08-06T21:23:18.105ssss2
  5. -------2019-08-06T21:23:18.105ssss4
  6. -------2019-08-06T21:23:19.110ssss8
  7. -------2019-08-06T21:23:19.110ssss6
  8. -------2019-08-06T21:23:19.110ssss5
  9. -------2019-08-06T21:23:19.110ssss7
  10. -------2019-08-06T21:23:19.110ssss9
  11. -------2019-08-06T21:23:20.113ssss10
  12. -------2019-08-06T21:23:20.113ssss12
  13. -------2019-08-06T21:23:20.113ssss13
  14. -------2019-08-06T21:23:20.113ssss11
  15. -------2019-08-06T21:23:20.113ssss14
  16. -------2019-08-06T21:23:21.117ssss18
  17. -------2019-08-06T21:23:21.117ssss16
  18. -------2019-08-06T21:23:21.117ssss17
  19. -------2019-08-06T21:23:21.117ssss15
  20. -------2019-08-06T21:23:21.117ssss19

可以看到每5个一组一组的运行,

过程:corePoolSize→queueCapacity→开启maxPoolSize

  1. 当一个新任务来临时:
  2. 1)如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务;
  3. 2)如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列;
  4. 3)如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务;
  5. 4)如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务;
  6. 5)当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,如果allowCoreThreadTimeOutfalse,则线程数量维持在corePoolSize 如果为true,则线程数量可最低降至0

1.2、使用task:executor方式

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:task="http://www.springframework.org/schema/task"
  5. xsi:schemaLocation=
  6. "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
  8.  
  9. <!-- 包路径扫描 -->
  10. <context:component-scan base-package="spring.task"/>
  11.  
  12. <!-- 定义线程池 -->
  13. <task:executor id="executor" pool-size="5" queue-capacity="10" rejection-policy="DISCARD_OLDEST"/>
  14.  
  15. </beans>

java 测试

  1. @Component
  2. public class AsyncTask {
  3.  
  4. @Autowired
  5. private ThreadPoolTaskExecutor executor;
  6.  
  7. @PostConstruct
  8. public void testAsycTask() {
  9. for (int i = 0; i < 10; i++) {
  10. executor.execute(new Runnable() {
  11. public void run() {
  12. asyncTask();
  13. }
  14. });
  15. }
  16. }
  17.  
  18. private void asyncTask(){
  19. System.out.println( "---" + Thread.currentThread().getName());
  20. }
  21. }

二、池子如何配置参数

2.1、默认值

   corePoolSize=1
  queueCapacity=Integer.MAX_VALUE
  maxPoolSize=Integer.MAX_VALUE
  keepAliveTime=60s
  allowCoreThreadTimeout=false
  rejectedExecutionHandler=AbortPolicy()

2.2、如何设置

需要根据几个值来决定

  - tasks :每秒的任务数,假设为100~1000

  - taskcost:每个任务花费时间,假设为0.1s

  - responsetime:系统允许容忍的最大响应时间,假设为2s

配置计算

  - corePoolSize = 每秒需要多少个线程处理?

    * threadcount = tasks/(1/taskcost) =tasks*taskcout = (100~1000)*0.1 = 10~100 个线程。corePoolSize设置应该大于10

    * 根据8020原则,如果80%的每秒任务数小于200,那么corePoolSize设置为20即可

  - queueCapacity = (coreSizePool/taskcost)*responsetime

    * 计算可得 queueCapacity = 20/0.1*2 = 400。意思是队列里的线程可以等待4s,超过了的需要新开线程来执行

    * 切记不能写:LinkedBlockingQueue queue = new LinkedBlockingQueue(); 实际是设置为Integer.MAX_VALUE,这样队列会很大,线程数只会保持在corePoolSize大小,当任务陡增时,不能新开线程来执行,响应时间会随之陡增。

  - maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)

    * 计算可得 maxPoolSize = (1000-400)/10 = 60

    * (最大任务数-队列容量)/每个线程每秒处理能力 = 最大线程数

  - rejectedExecutionHandler:根据具体情况来决定,任务不重要可丢弃,任务重要则要利用一些缓冲机制来处理

  - keepAliveTime和allowCoreThreadTimeout采用默认通常能满足

  以上都是理想值,实际情况下要根据机器性能来决定。如果在未达到最大线程数的情况机器cpu load已经满了,则需要通过升级硬件和优化代码,降低taskcost来处理。

xml

007-多线程-JUC线程池-Spring线程池配置、池子如何配置参数的更多相关文章

  1. Java多线程系列 JUC线程池04 线程池原理解析(三)

    转载 http://www.cnblogs.com/skywang12345/p/3509954.html  https://blog.csdn.net/qq_22929803/article/det ...

  2. Java多线程系列 JUC线程池07 线程池原理解析(六)

     关闭“线程池” shutdown()的源码如下: public void shutdown() { final ReentrantLock mainLock = this.mainLock; // ...

  3. Java多线程系列 JUC线程池03 线程池原理解析(二)

    转载  http://www.cnblogs.com/skywang12345/p/3509954.html  http://www.cnblogs.com/skywang12345/p/351294 ...

  4. Java多线程系列 JUC线程池02 线程池原理解析(一)

    转载  http://www.cnblogs.com/skywang12345/p/3509960.html ; http://www.cnblogs.com/skywang12345/p/35099 ...

  5. Java多线程系列 JUC线程池01 线程池框架

    转载  http://www.cnblogs.com/skywang12345/p/3509903.html 为什么引入Executor线程池框架 new Thread()的缺点 1. 每次new T ...

  6. Spring线程池开发实战

    Spring线程池开发实战 作者:chszs,转载需注明. 作者博客主页:http://blog.csdn.net/chszs 本文提供了三个Spring多线程开发的例子,由浅入深,由于例子一目了然, ...

  7. Java多线程学习(八)线程池与Executor 框架

    目录 历史优质文章推荐: 目录: 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 2.3 Executor 框架的使用示意图 ...

  8. Spring线程池ThreadPoolTaskExecutor配置及详情

    Spring线程池ThreadPoolTaskExecutor配置及详情 1. ThreadPoolTaskExecutor配置 <!-- spring thread pool executor ...

  9. spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue

    一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...

随机推荐

  1. 神经网络(10)--有助于对神经网络Backpropagation算法的理解

    为了更好的理解backpropagation,先来了解一下forward propagation的内部 我们在forward propagation中计算Z1(3)的方法与在back propagat ...

  2. MySQL复制介绍及搭建

    MySQL复制介绍 MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再解析日志并应用到自身,类似Oracle中的Data Guard. M ...

  3. python数据分析之数据分布

    转自链接:https://blog.csdn.net/YEPAO01/article/details/99197487 一.查看数据分布趋势 import pandas as pd import nu ...

  4. 拉格朗日插值matlab实现

    已给sin0.32=0.314567,sin0.34=0.333487,sin0.36=0.352274,用线性插值及抛物插值计算sin0.3367的值并估计截断误差. 1. 线性插值 clc;cle ...

  5. LightOJ - 1259 - Goldbach`s Conjecture(整数分解定理)

    链接: https://vjudge.net/problem/LightOJ-1259 题意: Goldbach's conjecture is one of the oldest unsolved ...

  6. Zookeeper中的watcher监听和leader选举机制

    watcher监听 什么是watcher接口 同一个事件类型在不同的通知状态中代表的含义有所不同,下图列举了常见的通知状态和事件类型. Watcher通知状态与事件类型一览 上图列举了ZooKeepe ...

  7. javaweb学习笔记(三)

    一.javaweb高级(Filter和Listener)的简单介绍 1.过滤器Filter (https://www.cnblogs.com/vanl/p/5742501.html) ①定义 Filt ...

  8. Oracle ALERT日志中常见监听相关报错之二:ORA-3136错误的排查 (转载)

    近期在多个大型系统中遇到此问题,一般来说如果客户端未反映异常的话可以忽略的.如果是客户端登陆时遇到ORA-12170: TNS:Connect timeout occurred,可以参考 http:/ ...

  9. Linux 命令 ipcs/ipcrm

    ipcs 1. 命令格式 ipcs [resource-option] [output-format] ipcs [resource-option] -i id 2. 命令功能 提供IPC设备的信息 ...

  10. GDB的安装

    1.下载GDB7.10.1安装包 #wget http://ftp.gnu.org/gnu/gdb/gdb-7.10.1.tar.gz或者可以远程看下有哪些版本 http://ftp.gnu.org/ ...