ExecutorService与ThreadPoolTaskExecutor
1.ExecutorService
private static ExecutorService exec = null;
public static ExecutorService getExecutorServiceInstance(){
if(exec == null){
exec = Executors.newCachedThreadPool();
}
return exec;
}
public void threadNoticeOrMessageOrShortMessage (Integer type, Map<String, String> map, List<String> replaceParameter, List<String> list, Integer saveFlag){
exec = getExecutorServiceInstance();
NoticeOrMessageOrShortMessage noticeOrMessageOrShortMessage = new NoticeOrMessageOrShortMessage(getMessagePushInstance(), type, map, replaceParameter, list, saveFlag,
messagePushService, sendPushService, sendSmsService, sendMessageService);
exec.execute(noticeOrMessageOrShortMessage);
}
2.ThreadPoolTaskExecutor
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${task.core_pool_size}" />
<property name="maxPoolSize" value="${task.max_pool_size}" />
<property name="queueCapacity" value="${task.queue_capacity}" />
<property name="keepAliveSeconds" value="${task.keep_alive_seconds}" />
<!-- 新增 -->
- <!-- 线程池对拒绝任务(无线程可用)的处理策略 -->
- <property name="rejectedExecutionHandler">
- <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
- </property>
</bean>
@Resource(name = "taskExecutor")
private TaskExecutor taskExecutor;
private void addSendTask(final MimeMessage mimeMessage) {
try {
taskExecutor.execute(new Runnable() {
public void run() {
javaMailSender.send(mimeMessage);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
另外一种方式(未验证代码准确性)
private static ThreadPoolTaskExecutor threadPoolTaskExecutor = null;
public static ThreadPoolTaskExecutor getThreadPoolTaskExecutor Instance(){
if(threadPoolTaskExecutor == null){
threadPoolTaskExecutor.setCorePoolSize(5);
threadPoolTaskExecutor.setMaxPoolSize(50);
threadPoolTaskExecutor.setQueueCapacity(1000);
threadPoolTaskExecutor.setKeepAliveSeconds(60);
try {
taskExecutor.execute(new Runnable() {
public void run() {
javaMailSender.send(mimeMessage);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
return exec;
} 下面分别说下各项代表的具体意义: int corePoolSize:线程池维护线程的最小数量.
int maximumPoolSize:线程池维护线程的最大数量.
long keepAliveTime:空闲线程的存活时间.
TimeUnit unit: 时间单位,现有纳秒,微秒,毫秒,秒枚举值.
BlockingQueue<Runnable> workQueue:持有等待执行的任务队列.
RejectedExecutionHandler handler:
用来拒绝一个任务的执行,有两种情况会发生这种情况。
一是在execute方法中若addIfUnderMaximumPoolSize(command)为false,即线程池已经饱和;
二是在execute方法中, 发现runState!=RUNNING || poolSize == 0,即已经shutdown,就调用ensureQueuedTaskHandled(Runnable command),在该方法中有可能调用reject。 Reject策略预定义有四种:
(1)ThreadPoolExecutor.AbortPolicy策略,是默认的策略,处理程序遭到拒绝将抛出运行时 RejectedExecutionException。
(2)ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃.
(3)ThreadPoolExecutor.DiscardPolicy策略,不能执行的任务将被丢弃.
(4)ThreadPoolExecutor.DiscardOldestPolicy策略,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程).
ThreadPoolExecutor执行器的处理流程:
(1)当线程池大小小于corePoolSize就新建线程,并处理请求.
(2)当线程池大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理.
(3)当workQueue放不下新入的任务时,新建线程加入线程池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理.
(4)另外,当线程池的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁.
CachedThreadPool
CachedThreadPool会创建一个缓存区,将初始化的线程缓存起来。会终止并且从缓存中移除已有60秒未被使用的线程。
如果线程有可用的,就使用之前创建好的线程,
如果线程没有可用的,就新创建线程。
- 重用:缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse;如果没有,就建一个新的线程加入池中
- 使用场景:缓存型池子通常用于执行一些生存期很短的异步型任务,因此在一些面向连接的daemon型SERVER中用得不多。
- 超时:能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。
- 结束:注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。
FixedThreadPool
在FixedThreadPool中,有一个固定大小的池。
如果当前需要执行的任务超过池大小,那么多出的任务处于等待状态,直到有空闲下来的线程执行任务,
如果当前需要执行的任务小于池大小,空闲的线程也不会去销毁。
重用:fixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程
固定数目:其独特之处在于,任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
超时:和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),
使用场景:所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器
源码分析:从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同:
1.fixed池线程数固定,并且是0秒IDLE(无IDLE)
2.cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE
创建了一个固定大小的线程池,容量为3,然后循环执行了4个任务。由输出结果可以看到,前3个任务首先执行完,然后空闲下来的线程去执行第4个任务。
SingleThreadExecutor
SingleThreadExecutor得到的是一个单个的线程,这个线程会保证你的任务执行完成。
如果当前线程意外终止,会创建一个新线程继续执行任务,这和我们直接创建线程不同,也和newFixedThreadPool(1)不同。
ScheduledThreadPool
ScheduledThreadPool是一个固定大小的线程池,与FixedThreadPool类似,执行的任务是定时执行。
参考:http://www.cnblogs.com/cuiliang/p/3327039.html
http://zy116494718.iteye.com/blog/1704344
ExecutorService与ThreadPoolTaskExecutor的更多相关文章
- java 线程池(ExecutorService与Spring配置threadPoolTaskExecutor)
一.java ExecutorService实现 创建ExecutorService变量private ExecutorService executor = null 2.执行对应任务时,首先生成线程 ...
- SpringBoot开始多线程
增加配置类 package com.springbootdemo.demo.config; import org.springframework.context.annotation.Bean; im ...
- JAVA线程池学习,ThreadPoolTaskExecutor和ThreadPoolExecutor有何区别?
初学者很容易看错,如果没有看到spring或者JUC源码的人肯定是不太了解的. ThreadPoolTaskExecutor是spring core包中的,而ThreadPoolExecutor是JD ...
- Executor, ExecutorService 和 Executors 间的不同
java.util.concurrent.Executor, java.util.concurrent.ExecutorService, java.util.concurrent. Executors ...
- Future、 CompletableFuture、ThreadPoolTaskExecutor简单实践
一 Future(jdk5引入) 简介: Future接口是Java多线程Future模式的实现,可以来进行异步计算. 可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算 ...
- SPRING中的线程池ThreadPoolTaskExecutor(转)
转自:https://blog.csdn.net/zhanglongfei_test/article/details/51888433 一.初始化 1,直接调用 ThreadPoolTaskExecu ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- 【SSM Spring 线程池 OJ】 使用Spring线程池ThreadPoolTaskExecutor
最近做的Online Judge项目,在本地判题的实现过程中,遇到了一些问题,包括多线程,http通信等等.现在完整记录如下: OJ有一个业务是: 用户在前端敲好代码,按下提交按钮发送一个判题请求给后 ...
- ThreadPoolTaskExecutor学习
1. ThreadPoolTaskExecutor学习 1.1. 前言 我们知道一般创建线程池,我们都用ThreadPoolExecutor,但实际上Spring它也对该线程池做了一层封装,他就是Th ...
随机推荐
- 用任务计划管理计划任务对付任务计划-禁止WPS提示升级
作为一名至今还在坚守着64位XP的XP用到死星人,因为准备升级电脑,所以准备移民外星,开始使用Windows7.其实我新电脑买来一年了,为了坚守XP,扔在一边没有装(华硕Z9PE-D8 WS主板,双E ...
- iOS 企业设备管理 补充中。。。
公司的设备都有一个统一的管理方法,以前不太明白,今天看了一下资料. 这里解释了什么是设备管理 Profile Manager creates and distributes configuration ...
- 简化MSI在WIN10的安装
这里给大家分享一个简化MSI安装的工具 InstallByDrag: 在win10系统中,通过双击方式打开 MSI 安装文件,可能被提示由于dll加载问题无法安装,这是由于没有使用管理员权限运行.而M ...
- sqlserver添加主键
sqlServer中给表添加主键的sql: alter table market_media_medical_history alter column pk_id bigint not null; a ...
- java写RelativeLayout 的属性
有时项目需要动态的调整一下布局,需要改变一些view的位置属性等等. 直接下代码 RelativeLayout.LayoutParams params=new RelativeLayout.Layou ...
- Java异常处理机构(日常笔记)
try{ 需要保护的代码块 }catch(异常类型 实例){ 捕捉到异常时的代码处理块 }[可有0~多个catch语句] finaly{ 不管异常是否发生都要执行的代码块}
- Idea 快捷键
Ctrl+Alt+T 选中代码块加try catch等常用快捷操作.如图: psvm+Tab键 快速创建main方法 pout+Tab键 快速打出System.out.println(); Ctrl+ ...
- 分布式之ZookeeperMac安装
Zookeeper用于分布式计算中的协调员,观察员,观察者,分布式锁,在系统中利用Zookeeper来处理事件通知,队列,锁等功能. 使用brew安装 zookeeper. 可参考:http://bl ...
- oracle对/dev/shm的使用
查看共享内存打开的文件数 [root@db2 ~]# lsof -n | grep /dev/shm | wc -l 34693 共享内存中总共文件数 [root@db2 ~]# ls -l /dev ...
- Linux 使用Crontab设置定时调用Shell文件
定时执行步骤: 利用crontab来定时执行任务大致有如下两步: 1.编写shell脚本 2.利用crontab加入到定时任务队列 一.如何建立shell脚本 程序必须以下面的行开始(必须方在文件的第 ...