线程池解析

 1.项目中多线程的使用

1.1 多线程代码

public class PreLoanController extends BaseController {
	
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private static final String SUCCESS_CODE = "0000";//返回成功码
	private static final String FAILURE_CODE = "9999";//返回失败码
	
	@Value("${key_aes_apply}")
	private String AES_KEY;//进件AES密钥
	
    @Autowired
    private PreLoanService preLoanService;
    
    @Autowired
	private ThreadPoolTaskExecutor taskExecutor;
   
    /**
     * 预审接口
     *
     * @throws Exception
     */
    @RequestMapping(value = "/apply", method = RequestMethod.POST)
    public @ResponseBody JSONObject apply(HttpServletRequest request, HttpServletResponse response){
    	String plainContent = "";
    	try {
        	plainContent = request.getParameter("plainContent");
        	if(StringUtils.isBlank(plainContent)){
        		return ResponseVO.failure(FAILURE_CODE,"请求参数不能为空");
        	}
        	
        	//自测不加密----后期删除该代码
        	String type = request.getParameter("type");
        	if(StringUtils.isBlank(type)){
        		plainContent = AESUtil.decrypt(plainContent, AES_KEY);
        	}
        	
        	logger.info("解密后参数plainContent:{}", plainContent);
        	if(StringUtils.isBlank(plainContent)){
        		return ResponseVO.failure(FAILURE_CODE,"请求参数解决异常");
        	}
        	PreLoanApply apply = JSON.parseObject(plainContent, PreLoanApply.class);
        	
        	String strRequestNo = apply.getStrRequestNo();//请求编号
        	if(StringUtils.isBlank(strRequestNo) || StringUtils.isBlank(apply.getFlowNo())) {
        		return ResponseVO.failure(FAILURE_CODE,"请求号或流程编号不能为空");
        	}
            
            int count = preLoanService.countByRequestNo(strRequestNo);
            if(count > 0){
            	logger.info("订单号["+strRequestNo+"]已经存在,不能重复进件");
            	return ResponseVO.failure(FAILURE_CODE,"订单["+strRequestNo+"]已经存在,不能重复进件");
            }
            ApplyJson info = new ApplyJson();
            info.setId(GeneratorUUID.getId());
        	info.setCreateDate(DateUtils.formatDate(new Date(),"yyyy-MM-dd HH:mm:ss"));
        	info.setStrRequest(plainContent);
        	info.setStrRequestNo(apply.getStrRequestNo());
        	info.setCustomerno(apply.getBaseInfo().getCustomerno());
        	info.setType("3");
        	preLoanService.saveApplyJSON(info);
        	
            
            //基础参数校验
            ValidationResult validationResult = ValidationUtils.validateEntity(apply.getBaseInfo());
            if (validationResult.isHasErrors()) {
                Map<String, String> errorMsg = validationResult.getErrorMsg();
                logger.info("参数校验不通过[{}]:{}",strRequestNo,errorMsg);
                return ResponseVO.failure(FAILURE_CODE,"参数校验不通过["+errorMsg+"]");
            }
            
            //开启多线程处理数据
            taskExecutor.execute(new Runnable() {
    			@Override
    			public void run() {
    				JSONObject res = handle(apply);
    	            logger.info("进件结果[{}]:{}", strRequestNo,res);
    			}
    		});
            
			return ResponseVO.success(SUCCESS_CODE);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("Fail = " + e.getMessage());
            return ResponseVO.failure(FAILURE_CODE,"请求异常["+e.getMessage()+"]");
        }
    }     
    
}

1.2.线程池的配置

spring-context-thread.xml的配置如下:    

<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}" />
        <!-- 线程池维护线程所允许的空闲时间,默认为60s -->
        <property name="keepAliveSeconds" value="${task.keep_alive_seconds}" />
    </bean>

pom.xml文件添加依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>

1.3 ThreadPoolTaskExecutor的参数:

  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。

1.4 处理流程

当一个任务通过execute(Runnable)方法欲添加到线程池时: 
1、 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。 
2、 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。 
3、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。 
4、 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。 
5、 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

2 线程池源码解析

org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor类

@Override
public void execute(Runnable task) {
        //获取线程池执行对象
		Executor executor = getThreadPoolExecutor();
		try {
            //执行多线程任务
			executor.execute(task);
		}
		catch (RejectedExecutionException ex) {
			throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
		}
	}

public ThreadPoolExecutor getThreadPoolExecutor() throws IllegalStateException {
		Assert.state(this.threadPoolExecutor != null, "ThreadPoolTaskExecutor not initialized");
		return this.threadPoolExecutor;
}


@Override
protected ExecutorService initializeExecutor(
			ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
        //创建阻塞队列
		BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);
        //创建线程池执行对象
		ThreadPoolExecutor executor  = new ThreadPoolExecutor(
				this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
				queue, threadFactory, rejectedExecutionHandler);
		if (this.allowCoreThreadTimeOut) {
			executor.allowCoreThreadTimeOut(true);
		}

		this.threadPoolExecutor = executor;
		return executor;
}

//LinkedBlockingQueue  SynchronousQueue是BlockingQueue的实现类
protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
        //如果队列容量未满,创建LinkedBlockingQueue对象
		if (queueCapacity > 0) {
			return new LinkedBlockingQueue<Runnable>(queueCapacity);
		}
        //如果队列容量已满,创建SynchronousQueue对象
		else {
			return new SynchronousQueue<Runnable>();
		}
	}

TreadPoolExecutor的执行参考https://www.cnblogs.com/dolphin0520/p/3932921.html

猜你喜欢

转载自blog.csdn.net/qq_30219537/article/details/81099954
今日推荐