007-多线程-JUC线程池-Spring线程池配置、池子如何配置参数
一、概述
Spring通过ThreadPoolTaskExecutor实现线程池技术,它是使用jdk中的Java.util.concurrent.ThreadPoolExecutor进行实现。
1.1、xml方式配置
- <!-- Spring线程池 -->
- <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
- <!-- 核心线程数 -->
- <property name="corePoolSize" value="5" />
- <!-- 线程池维护线程的最大数量 -->
- <property name="maxPoolSize" value="10" />
- <!-- 允许的空闲时间, 默认60秒 -->
- <property name="keepAliveSeconds" value="60" />
- <!-- 任务队列 -->
- <property name="queueCapacity" value="50" />
- <!-- 线程超过空闲时间限制,均会退出直到线程数量为0 -->
- <property name="allowCoreThreadTimeOut" value="true"/>
- <!-- 对拒绝task的处理策略 -->
- <property name="rejectedExecutionHandler">
- <bean class="java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy" />
- </property>
- </bean>
java代码
- //帮我们创建容器
- @RunWith(SpringJUnit4ClassRunner.class)
- //指定创建容器时使用哪个配置文件
- @ContextConfiguration("classpath:applicationContext.xml")
- public class SpringThreadPoolExecutorTest {
- @Autowired
- private ThreadPoolTaskExecutor taskExecutor;
- @Test
- public void newFixedThreadPoolTestSubmit() throws Exception {
- List<Future<?>> list=new ArrayList<>();
- for (int i = 0; i < 20; i++) {
- Future<?> submit = taskExecutor.submit(new DataTask("ssss" + i));
- list.add(submit);
- }
- for (Future<?> future : list) {
- future.get();
- }
- }
- class DataTask implements Runnable {
- private String a;
- public DataTask(String a) {
- this.a = a;
- }
- @Override
- public void run() {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("-------"+ LocalDateTime.now()+a);
- }
- }
- }
输出
- -------2019-08-06T21:23:18.105ssss0
- -------2019-08-06T21:23:18.105ssss3
- -------2019-08-06T21:23:18.105ssss1
- -------2019-08-06T21:23:18.105ssss2
- -------2019-08-06T21:23:18.105ssss4
- -------2019-08-06T21:23:19.110ssss8
- -------2019-08-06T21:23:19.110ssss6
- -------2019-08-06T21:23:19.110ssss5
- -------2019-08-06T21:23:19.110ssss7
- -------2019-08-06T21:23:19.110ssss9
- -------2019-08-06T21:23:20.113ssss10
- -------2019-08-06T21:23:20.113ssss12
- -------2019-08-06T21:23:20.113ssss13
- -------2019-08-06T21:23:20.113ssss11
- -------2019-08-06T21:23:20.113ssss14
- -------2019-08-06T21:23:21.117ssss18
- -------2019-08-06T21:23:21.117ssss16
- -------2019-08-06T21:23:21.117ssss17
- -------2019-08-06T21:23:21.117ssss15
- -------2019-08-06T21:23:21.117ssss19
可以看到每5个一组一组的运行,
过程:corePoolSize→queueCapacity→开启maxPoolSize
- 当一个新任务来临时:
- 1)如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务;
- 2)如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列;
- 3)如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务;
- 4)如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务;
- 5)当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,如果allowCoreThreadTimeOut为false,则线程数量维持在corePoolSize, 如果为true,则线程数量可最低降至0;
1.2、使用task:executor方式
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:task="http://www.springframework.org/schema/task"
- xsi:schemaLocation=
- "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
- <!-- 包路径扫描 -->
- <context:component-scan base-package="spring.task"/>
- <!-- 定义线程池 -->
- <task:executor id="executor" pool-size="5" queue-capacity="10" rejection-policy="DISCARD_OLDEST"/>
- </beans>
java 测试
- @Component
- public class AsyncTask {
- @Autowired
- private ThreadPoolTaskExecutor executor;
- @PostConstruct
- public void testAsycTask() {
- for (int i = 0; i < 10; i++) {
- executor.execute(new Runnable() {
- public void run() {
- asyncTask();
- }
- });
- }
- }
- private void asyncTask(){
- System.out.println( "---" + Thread.currentThread().getName());
- }
- }
二、池子如何配置参数
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线程池配置、池子如何配置参数的更多相关文章
- Java多线程系列 JUC线程池04 线程池原理解析(三)
转载 http://www.cnblogs.com/skywang12345/p/3509954.html https://blog.csdn.net/qq_22929803/article/det ...
- Java多线程系列 JUC线程池07 线程池原理解析(六)
关闭“线程池” shutdown()的源码如下: public void shutdown() { final ReentrantLock mainLock = this.mainLock; // ...
- Java多线程系列 JUC线程池03 线程池原理解析(二)
转载 http://www.cnblogs.com/skywang12345/p/3509954.html http://www.cnblogs.com/skywang12345/p/351294 ...
- Java多线程系列 JUC线程池02 线程池原理解析(一)
转载 http://www.cnblogs.com/skywang12345/p/3509960.html ; http://www.cnblogs.com/skywang12345/p/35099 ...
- Java多线程系列 JUC线程池01 线程池框架
转载 http://www.cnblogs.com/skywang12345/p/3509903.html 为什么引入Executor线程池框架 new Thread()的缺点 1. 每次new T ...
- Spring线程池开发实战
Spring线程池开发实战 作者:chszs,转载需注明. 作者博客主页:http://blog.csdn.net/chszs 本文提供了三个Spring多线程开发的例子,由浅入深,由于例子一目了然, ...
- Java多线程学习(八)线程池与Executor 框架
目录 历史优质文章推荐: 目录: 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 2.3 Executor 框架的使用示意图 ...
- Spring线程池ThreadPoolTaskExecutor配置及详情
Spring线程池ThreadPoolTaskExecutor配置及详情 1. ThreadPoolTaskExecutor配置 <!-- spring thread pool executor ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
随机推荐
- 神经网络(10)--有助于对神经网络Backpropagation算法的理解
为了更好的理解backpropagation,先来了解一下forward propagation的内部 我们在forward propagation中计算Z1(3)的方法与在back propagat ...
- MySQL复制介绍及搭建
MySQL复制介绍 MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再解析日志并应用到自身,类似Oracle中的Data Guard. M ...
- python数据分析之数据分布
转自链接:https://blog.csdn.net/YEPAO01/article/details/99197487 一.查看数据分布趋势 import pandas as pd import nu ...
- 拉格朗日插值matlab实现
已给sin0.32=0.314567,sin0.34=0.333487,sin0.36=0.352274,用线性插值及抛物插值计算sin0.3367的值并估计截断误差. 1. 线性插值 clc;cle ...
- LightOJ - 1259 - Goldbach`s Conjecture(整数分解定理)
链接: https://vjudge.net/problem/LightOJ-1259 题意: Goldbach's conjecture is one of the oldest unsolved ...
- Zookeeper中的watcher监听和leader选举机制
watcher监听 什么是watcher接口 同一个事件类型在不同的通知状态中代表的含义有所不同,下图列举了常见的通知状态和事件类型. Watcher通知状态与事件类型一览 上图列举了ZooKeepe ...
- javaweb学习笔记(三)
一.javaweb高级(Filter和Listener)的简单介绍 1.过滤器Filter (https://www.cnblogs.com/vanl/p/5742501.html) ①定义 Filt ...
- Oracle ALERT日志中常见监听相关报错之二:ORA-3136错误的排查 (转载)
近期在多个大型系统中遇到此问题,一般来说如果客户端未反映异常的话可以忽略的.如果是客户端登陆时遇到ORA-12170: TNS:Connect timeout occurred,可以参考 http:/ ...
- Linux 命令 ipcs/ipcrm
ipcs 1. 命令格式 ipcs [resource-option] [output-format] ipcs [resource-option] -i id 2. 命令功能 提供IPC设备的信息 ...
- GDB的安装
1.下载GDB7.10.1安装包 #wget http://ftp.gnu.org/gnu/gdb/gdb-7.10.1.tar.gz或者可以远程看下有哪些版本 http://ftp.gnu.org/ ...