线程池示例代码

第一步:定义一个线程池

package com.ucf.trade.util.common;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.springframework.stereotype.Component;

/**
 * 线程池
 * Description: 
 * All Rights Reserved.
 * @version 1.0  2014年8月12日 下午3:57:16 
 */
@Component
public class ThreadPool {

	//阻塞队列深度
	private static int maxQueueSize;
	//核心线程数
	private static int corePoolSize;
	//最大线程数
	private static int maximumPoolSize;
	//线程池中的阻塞队列,请求数大于核心线程数时进阻塞队列等待
	private static ArrayBlockingQueue<Runnable> queue;
	//线程池
	private static ThreadPoolExecutor pool;
	
	static {
		maxQueueSize = Integer.parseInt(Constant.getValue(Constant.ThreadPoolQueueSize));
		corePoolSize = Integer.parseInt(Constant.getValue(Constant.ThreadPoolSize));
		maximumPoolSize = Integer.parseInt(Constant.getValue(Constant.ThreadPoolSize));
		queue = new ArrayBlockingQueue<Runnable>(maxQueueSize);
		pool = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,3,TimeUnit.SECONDS,queue,new ThreadPoolExecutor.CallerRunsPolicy());//CallerRunsPolicy 超出线程池范围,立即开线程池外新线程处理,脱离线程池控制
	}
	/**
	 * 执行线程
	 * Description: 
	 * @Version1.0 2014年8月12日 下午3:56:08 by lianjing([email protected])创建
	 * @param task
	 */
	public void exec(Runnable task) {
		pool.execute(task);
	}
	/**
	 * 判断阻塞队列满
	 * Description: 
	 * @Version1.0 2014年8月12日 下午3:56:29 by lianjing([email protected])创建
	 * @return
	 */
	public boolean isFull() {
		return getQueue().size() == maxQueueSize;
	}
	
	public ArrayBlockingQueue<Runnable> getQueue() {
		return queue;
	}
	public int getQueueSize() {
		return queue.size();
	}
}


第二步:创建一个bean 工厂,用来获取某个类实例

package com.ucf.trade.util.common;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactory implements BeanFactoryAware {
	//spring工厂
	private BeanFactory beanFactory ;
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;
	}
	
	public Object getBean(String name) {
        return beanFactory.getBean(name);
    }
 
    public <T> T getBean(String name, Class<T> clazz) {
        return (T)beanFactory.getBean(name);
    }
}

第三步:定义任务类

package com.ucf.trade.schedule;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.ucf.platform.framework.core.log.UcfLogger;
import com.ucf.platform.framework.core.log.UcfLoggerFactory;
import com.ucf.trade.component.BatchPersistence;
import com.ucf.trade.pojo.UcfBatchOrderDetail;
import com.ucf.trade.util.common.Constant;
import com.ucf.trade.util.common.MyBeanFactory;
import com.ucf.trade.util.common.ThreadPool;

@Component
public class WithdrawBatchTask {
	private final static UcfLogger logger = UcfLoggerFactory.getLogger(WithdrawBatchTask.class);
	
	@Resource
	private MyBeanFactory myBeanFactory;
	@Resource
	private ThreadPool threadPool;
	@Resource
	private BatchPersistence batchPersistence;
	
	public void execTask() {
		logger.info("【批量代发-后台任务】开始扫描待处理订单。。。");
		try {
			/*
			 * 1.判断队列深度
			 */
			if(threadPool.isFull()) {
				logger.info("【批量代发-后台任务】当前线程池阻塞队列深度已达到最大,暂停扫描,队列深度为:" + threadPool.getQueueSize());
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					logger.error(e.getMessage(), e);
				}
			}
			//2.扫描待处理记录
			List<UcfBatchOrderDetail> detailList = batchPersistence.queryDetailListForWait();
			int detailSize = detailList.size();
			logger.info("【批量代发-后台任务】本次扫描待处理订单数量为:" + detailSize);
			
			//3.分配线程处理
			for(UcfBatchOrderDetail detail : detailList) {
				BatchExecutor batchExecutor = myBeanFactory.getBean("batchExecutor",BatchExecutor.class);
				batchExecutor.setUcfBatchOrderDetail(detail);
				logger.info("【批量代发-后台任务】merchantNo:{},加入线程队列,等待执行。", detail.getMerchantNo());
				threadPool.exec(batchExecutor);
			}
			
			/*
			 * 4.持续扫描判断
			 * 本次没有记录,停顿5分钟
			 * 否则停顿时间为本次记录数除以最大线程数取整 + 1,单位秒
			 * 保证给每个线程留1秒处理时间
			 * 防止重复扫描到相同订单太多
			 */
			
			if(detailSize == 0) {
				try {
					Thread.sleep(5 * 60 * 1000);
				} catch (InterruptedException e) {
					logger.error(e.getMessage(), e);
				}
			} else {
				int poolSize = Integer.parseInt(Constant.getValue(Constant.ThreadPoolSize));
				int sleepTime = detailSize / poolSize + 1;
				try {
					Thread.sleep(sleepTime * 1000);
				} catch (InterruptedException e) {
					logger.error(e.getMessage(), e);
				}
			}
		} catch(Exception e) {
			logger.error(e.getMessage(), e);
			logger.info("【批量代发-后台任务】处理订单出现异常:{}", e.getMessage());
		}
		
		logger.info("【批量代发-后台任务】本次扫描完成。");
	}
	
}

第四步:定义具体的实现类

package com.ucf.trade.schedule;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.ucf.onlinepay.framework.common.util.StringUtil;
import com.ucf.platform.framework.core.log.UcfLogger;
import com.ucf.platform.framework.core.log.UcfLoggerFactory;
import com.ucf.trade.component.BatchPersistence;
import com.ucf.trade.dubbo.bo.WithdrawParamBo;
import com.ucf.trade.dubbo.bo.WithdrawReturnBo;
import com.ucf.trade.dubbo.service.WithdrawService;
import com.ucf.trade.pojo.UcfBatchOrder;
import com.ucf.trade.pojo.UcfBatchOrderDetail;
import com.ucf.trade.util.common.TimeUtil;
import com.ucf.trade.util.enums.TradeEnum;
import com.ucf.trade.util.exception.ErrorCode;

@Component
@Scope("prototype")
public class BatchExecutor implements Runnable {
	private final static UcfLogger logger = UcfLoggerFactory.getLogger(BatchExecutor.class);
	
	private UcfBatchOrderDetail ucfBatchOrderDetail;
	@Resource
	private BatchPersistence batchPersistence;
	@Resource
	private WithdrawService withdrawService;
	@Resource(name = "sharedTransactionTemplate")
	private TransactionTemplate transactionTemplate; // 手动提交事务
	
	@Override
	public void run() {
		logger.info("【批量代发-后台任务】merchantNo:{},开始执行,调用单笔接口。", ucfBatchOrderDetail.getMerchantNo());
		transactionTemplate.execute(new TransactionCallback<Object>() {
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try {
					//1.锁批量明细表当前记录
					UcfBatchOrderDetail lockDetail = new UcfBatchOrderDetail();
					lockDetail = batchPersistence.queryOrderDetailAndLock(ucfBatchOrderDetail);
					if(lockDetail == null || lockDetail.getStatus().equals(TradeEnum.PRE_PAY_SUCCESS.getCode())) {
						return null;
					}
					//2.参数准备
					WithdrawParamBo withdrawParamBo = new WithdrawParamBo();
					BeanUtils.copyProperties(withdrawParamBo, ucfBatchOrderDetail);
					withdrawParamBo.setBankCardNo(ucfBatchOrderDetail.getAccountNo());
					withdrawParamBo.setBankCardUserName(ucfBatchOrderDetail.getAccountName());
					withdrawParamBo.setSubType(TradeEnum.TRANS_WITHDRAW_SUBTYPE_BATCH.getCode());
					//获取noticeUrl
					UcfBatchOrder ucfBatchOrder = new UcfBatchOrder();
					ucfBatchOrder.setBatchNo(ucfBatchOrderDetail.getBatchNo());
					List<UcfBatchOrder> batchOrderList = batchPersistence.queryUcfBatchOrderByWhere(ucfBatchOrder);
					if(batchOrderList.size() > 0) {
						withdrawParamBo.setNoticeUrl(batchOrderList.get(0).getNoticeUrl());
					}
					
					//3.调用单笔代发
					WithdrawReturnBo withdrawReturnBo = withdrawService.withdraw(withdrawParamBo);
					
					//4.修改当前记录为已处理
					UcfBatchOrderDetail updateCondition = new UcfBatchOrderDetail();
					if(withdrawReturnBo.getResCode() != null && withdrawReturnBo.getResCode().equals(ErrorCode.OUT_ERROR_10005.getCode())) {
						updateCondition.setStatus(TradeEnum.FAIL.getCode());
						updateCondition.setResCode(withdrawReturnBo.getResCode());
						updateCondition.setResMessage(withdrawReturnBo.getResMessage());
					} else if(withdrawReturnBo.getStatus().equals(TradeEnum.WAIT.getCode())) {
						updateCondition.setStatus(TradeEnum.PRE_PAY_SUCCESS.getCode());
					} else {
						if(StringUtil.isEmpty(withdrawReturnBo.getStatus())) {
							updateCondition.setStatus(TradeEnum.FAIL.getCode());
							updateCondition.setMessage(withdrawReturnBo.getResMessage());
							updateCondition.setResCode(withdrawReturnBo.getResCode());
						} else {
							if(withdrawReturnBo.getStatus().equals(TradeEnum.SUCCESS.getCode())){
							    updateCondition.setStatus(withdrawReturnBo.getStatus());
							  }else{
								  updateCondition.setStatus(withdrawReturnBo.getStatus());
								  updateCondition.setMessage(withdrawReturnBo.getResMessage());
								  updateCondition.setResCode(withdrawReturnBo.getResCode());
							  }
						}
						updateCondition.setMessage(withdrawReturnBo.getResMessage());
					}
					updateCondition.setId(ucfBatchOrderDetail.getId());
					if(!StringUtil.isEmpty(withdrawReturnBo.getTradeTime())) {
						updateCondition.setTradeTime(TimeUtil.getDateFromDATETIME14(withdrawReturnBo.getTradeTime()));
					}
					updateCondition.setGmtModify(new Date());
					batchPersistence.updateUcfBatchOrderDetail(updateCondition);
					
				} catch(Exception e) {
					status.setRollbackOnly();
				}
				return null;
			}
		});
	}
	
	public UcfBatchOrderDetail getUcfBatchOrderDetail() {
		return ucfBatchOrderDetail;
	}
	public void setUcfBatchOrderDetail(UcfBatchOrderDetail ucfBatchOrderDetail) {
		this.ucfBatchOrderDetail = ucfBatchOrderDetail;
	}
}


部分常量定义:

public class Constant {
	private final static UcfLogger logger = UcfLoggerFactory.getLogger(Constant.class);
	 
	
	public static String ThreadPoolSize = "ThreadPoolSize";
	public static String ThreadPoolQueueSize = "ThreadPoolQueueSize";
	public static String PerMaxCount = "PerMaxCount";
}

以上代码仅供自己参考

你可能感兴趣的:(线程池示例代码)