Spring线程池ThreadPoolTaskExecutor

配置
<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();
        }
    }
}
于线程池中增加线程
@Resource
private 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,线程将被终止。这样,线程池可以动态的调整池中的线程数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值