1. Spring线程池的用法
1.1 通过xml配置的方法
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 线程池维护线程的最少数量 -->
<property name="corePoolSize" value="8" />
<!-- 线程池维护线程所允许的空闲时间 -->
<property name="keepAliveSeconds" value="300" />
<!-- 线程池维护线程的最大数量 -->
<property name="maxPoolSize" value="16" />
<!-- 线程池所使用的缓冲队列 -->
<property name="queueCapacity" value="1000" />
<!-- 线程池对拒绝任务(无线程可用)的处理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$AbortPolicy" />
</property>
</bean>
1.2 通过代码配置的方式
@Bean(name = "taskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
//线程池维护线程的最少数量
poolTaskExecutor.setCorePoolSize(8);
//线程池维护线程所允许的空闲时间
poolTaskExecutor.setKeepAliveSeconds(300);
//线程池维护线程的最大数量
poolTaskExecutor.setMaxPoolSize(16);
//线程池所使用的缓冲队列
poolTaskExecutor.setQueueCapacity(1000);
//配置拒绝策略
poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return poolTaskExecutor;
}
1.3 使用方式简单分析
通过上面的使用方式可以看出,主要有这几个参数:
• corePoolSize: 核心线程数,线程池中活着的最小的线程数量
• maxPoolSize:最大线程数,即线程池中最大的线程数量
• keepAliveSeconds:超过核心线程数的时候,空闲的线程允许等待的最长时间,单位秒
• queueCapacity: 队列容量,用于存放等待中的任务的队列容量
• rejectedExecutionHandler:线程池拒绝策略,当队列满了之后,以哪种方式处理新的任务
1.4 如果只是想简单看一下用法的话,就不用再向下看了
2. ThreadPoolTaskExecutor 结构分析
观察其主要代码发现,spring的线程池,主要是对Java原生线程池的一个封装:
private final Object poolSizeMonitor = new Object();
private int corePoolSize = 1;
private int maxPoolSize = Integer.MAX_VALUE;
private int keepAliveSeconds = 60;
private boolean allowCoreThreadTimeOut = false;
private int queueCapacity = Integer.MAX_VALUE;
// ####### 这里就是Java原生的线程池 #######
private ThreadPoolExecutor threadPoolExecutor;
所有的线程池相关的主要操作,也都是依赖于原生的Java线程池来实现的!!!!
- 从上面的UML图可以看出,左边主要是spring初始化或者销毁的时候,去初始化线程池一些内容;
- ExecutorConfigurationSupport :主要实现了借助Spring 实现线程池的初始化和销毁、拒绝策略
其中,拒绝策略也是使用了Java原生的,包括:
AbortPolicy:拒绝任务,并抛出异常
CallerRunsPolicy:交给线程池的调用方来执行
DiscardOldestPolicy: 丢弃队列中,最旧的任务
DiscardPolicy:丢弃当前的任务
- InitializingBean:通过实现afterPropertiesSet,来实现spring bean初始化的时候,线程池的初始化和销毁
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
- DisposableBeanL: spring bean销毁的时候,线程池的销毁
- 右边则主要是,定义了线程池的一些主要操作:
- void execute(Runnable task, long startTimeout);
单纯的执行任务,没有任何返回结果,也无法获取执行情况 - Future<?> submit(Runnable task);
返回一个Future,通过future.get,返回null, 表示结果完成 - Future submit(Callable task);
返回一个Future,通过future.get 返回Callable的执行结果,来表示执行完成