Spring线程池ThreadPoolTaskExecutor
来源:互联网 发布:世辉律师事务所 知乎 编辑:程序博客网 时间:2024/06/09 19:46
配置
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心线程数,维护线程的最少数量 --> <property name="corePoolSize" value="5"/> <!-- 最大线程数,维护线程的最大数量 --> <property name="maxPoolSize" value="10"/> <!-- 缓存队列 --> <property name="queueCapacity" value="5"/> <!-- 线程池维护线程所允许的空闲时间,默认为60s --> <property name="keepAliveSeconds" value="60"/> <property name= "rejectedExecutionHandler" > <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 --> <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 --> <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <bean class = "java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property></bean>
定义Runnable 的实现类
public class DownLoadTask implements Runnable { private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(DownLoadTask.class); //@Resource private DownFileService downFileService; private String taskName; private Long taskId; public DownLoadTask(String taskName, Long taskId, DownFileService downFileService){ this.taskName = taskName; this.taskId = taskId; this.downFileService = downFileService; } @Override public void run() { String[] headers = {"订单编号","订单金额","订单状态"}; try { //File file = File.createTempFile(taskName, System.currentTimeMillis() + ".xls"); //String url = file.getCanonicalPath(); String url = "~/" + taskName + System.currentTimeMillis() + ".xls"; LOGGER.info("临时文件url--->>" + url + "任务id--->>" + taskId + "任务名称--->>" + taskName); downFileService.exportFile("订单导出",headers,url,"",0,taskId, taskName); //file.deleteOnExit(); }catch(Exception e) { LOGGER.error("订单导出失败",e); e.printStackTrace(); } }}
于线程池中增加线程
@Resourceprivate ThreadPoolTaskExecutor taskExecutor;taskExecutor.execute(new DownLoadTask(taskName,taskId,downFileService));
原理
线程的创建、任务的提交、任务的执行、线程的销毁都是交由私有成员ThreadPoolExecutor来处理的
public void execute(Runnable task) { ThreadPoolExecutor executor = this.getThreadPoolExecutor(); try { executor.execute(task); } catch (RejectedExecutionException var4) { throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, var4); }}/* * Support for execute(). * * Method execute() and its helper methods handle the various * cases encountered when new tasks are submitted. The main * execute() method proceeds in 3 steps: * * 1. If it appears that fewer than corePoolSize threads are * running, try to start a new thread with the given command as * its first task. The check here errs on the side of caution. * The call to addIfUnderCorePoolSize rechecks runState and pool * size under lock (they change only under lock) so prevents false * alarms that would add threads when it shouldn't, but may also * fail to add them when they should. This is compensated within * the following steps. * * 2. If a task can be successfully queued, then we are done, but * still need to compensate for missing the fact that we should * have added a thread (because existing ones died) or that * shutdown occurred since entry into this method. So we recheck * state and if necessary (in ensureQueuedTaskHandled) roll back * the enqueuing if shut down, or start a new thread if there are * none. * * 3. If we cannot queue task, then we try to add a new * thread. There's no guesswork here (addIfUnderMaximumPoolSize) * since it is performed under lock. If it fails, we know we are * shut down or saturated. * * The reason for taking this overall approach is to normally * avoid holding mainLock during this method, which would be a * serious scalability bottleneck. After warmup, almost all calls * take step 2 in a way that entails no locking. *//** * Executes the given task sometime in the future. The task * may execute in a new thread or in an existing pooled thread. * * If the task cannot be submitted for execution, either because this * executor has been shutdown or because its capacity has been reached, * the task is handled by the current <tt>RejectedExecutionHandler</tt>. * * @param command the task to execute * @throws RejectedExecutionException at discretion of * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted * for execution * @throws NullPointerException if command is null */public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated }}
1、当运行的线程数小于corePoolSize的时候 ,创建新的线程来处理被添加的任务。
2、如果线程数大于等于corePoolSize的时候,则将任务提交到workQueue队列中 。
3、如果此时线程池中的数量大于corePoolSize,且缓冲队列workQueue已满,则:
当线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务;
线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。
即处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
阅读全文
0 0
- Spring ThreadPoolTaskExecutor线程池
- Spring线程池ThreadPoolTaskExecutor
- spring线程池ThreadPoolTaskExecutor
- spring线程池ThreadPoolTaskExecutor
- Spring线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- Spring中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- SPRING中的线程池ThreadPoolTaskExecutor
- springboot+mybatis+redis+thymeleaf Web项目搭建 开箱即用
- .XML之一 如何编写一个.xml文档
- mysql数据库误删除后的数据恢复操作说明
- spring 深入理解 google Guice 依赖注入
- 让visual studio飞起来
- Spring线程池ThreadPoolTaskExecutor
- 反序列化工具
- 建议Linux操作系统初学者的学习线路图
- Spring Boot 快速上手(三)数据操作
- VS配置lib库问题
- C/C++ 生成[X,Y]内的随机数
- 基于opencv查看图像各像素点的RGB值
- HDU 5025:Saving Tang Monk (BFS + 状压)
- c++引用