项目中遇到一个问题:每2分钟触发一次的定时任务只执行一次!每次启动项目时,看到做补偿处理的定时任务确实被触发了,但是,定时任务只跑一次,而且,理论上只会取到10条数据,但是却取到了全部需要补偿的数据,让我很是诧异,于是决定研究一番,后来发现是每次作为起始点的参数被置为最终的id,导致第二次的起始点不是0,所以继续第一次未取到的数据往后做补偿处理了,如果数据足够多,第三次,第四次......起始点都会是上一次id的最大值,继续做处理,直到做完一轮,下次定时任务触发时,由于起始值已经是所有数据id的最大值,所以取不到需要补偿的数据,也就不能从头开始补偿了。
package com.weimob.saas.ec.payment.task;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.weimob.saas.ec.payment.utils.EnvInfoCheckUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
import com.weimob.saas.ec.common.util.SoaUtil;
import com.weimob.saas.ec.payment.constant.PaymentConstant;
import com.weimob.saas.ec.payment.dao.PaymentCompensationLogDao;
import com.weimob.saas.ec.payment.model.entity.PaymentCompensationLogEntity;
import com.weimob.saas.ec.payment.service.third.MessageThirdService;
import com.weimob.saas.ec.soa.utils.SpringBeanUtils;
import com.weimob.sendInnerEmail.util.MailUtil;
/**
* @description 补偿处理task
* @date 2017年10月1日 上午11:55:52
*/
public class PaymentCompensationTask {
private static final Logger LOGGER = LoggerFactory.getLogger(PaymentCompensationTask.class);
private String runTaskIp;
private Integer limitNum;
private PaymentCompensationLogDao paymentCompensationLogDao;
private MessageThirdService messageThirdService;
private Long maxId;
private String receiverEmailList;
private String receiverPhoneNoList;
private Integer sendEmailCountCondition;
private Integer sendTextMessageCountCondition;
private Integer maxSendEmailTimes;
private Integer maxSendTextMessageTimes;
/**
* 定时任务线程是否启动标志
*/
private static AtomicBoolean isCompensationTaskRunning = new AtomicBoolean(false);
public void handlePaymentCompensatioin() {
long startTime = System.currentTimeMillis();
String catStatus = Transaction.SUCCESS;
String catTypeName = "";
//1. 判断ip, 当前机器ip是否是配置的ip
if (!SoaUtil.getLocalIp().equals(runTaskIp)) {
LOGGER.error("payment compensation server ip " + (SoaUtil.getLocalIp() + " is not as same as " + runTaskIp));
return;
}
//判断定时任务的线程是否结束
if (isCompensationTaskRunning.compareAndSet(false, true)) {
try {
//2. 从数据库分页取出需要补偿的记录
List<PaymentCompensationLogEntity> logEntityList = null;
try {
logEntityList = paymentCompensationLogDao.queryPaymentCompensationLogList(maxId, limitNum);
} catch (Exception e) {
LOGGER.error("fail to query payment compensation log list", e);
catStatus = Transaction.FAIL;
}
//3. 遍历补偿日志,反射调用相对应的方法
if (!CollectionUtils.isEmpty(logEntityList)) {
for (PaymentCompensationLogEntity logEntity : logEntityList) {
//3.1 通过spring容器找出service
maxId = logEntity.getId();
boolean isPushSuccess = true;
String serviceName = logEntity.getServiceName();
String methodName = logEntity.getMethodName();
String parameterInput = logEntity.getParameterInput();
Object serviceBean = SpringBeanUtils.getBean(serviceName);
if (null == serviceBean) {
continue;
}
List<String> paramList = new ArrayList<String>();
//3.2 遍历出bean下面的方法
boolean isInvoked = false;
for (Class<?> beanInterface : serviceBean.getClass().getInterfaces()) {
long executeStartTime = System.currentTimeMillis();
try {
for (Method method : beanInterface.getMethods()) {
if (methodName.equals(method.getName())) {
Type[] types = method.getGenericParameterTypes();
List<Object> params = new ArrayList<Object>();
if (types.length == 1) {
paramList.add(parameterInput);
}
if (types.length > 1) {// 超过2个参数,将JSON参数转为List<String>,后续再逐个转为对应的对象
List<String> tmepList = JSON.parseArray(parameterInput, String.class);
paramList.clear();
paramList.addAll(tmepList);
}
if (types.length == paramList.size()) {// 参数数量必须相同
for (int i = 0; i < types.length; i++) {
params.add(JSON.parseObject(paramList.get(i), types[i]));
}
isInvoked = true;
catTypeName = serviceName + "." + methodName;
method.invoke(serviceBean, params.toArray());
break;
}
}
}
} catch (Exception e) {
LOGGER.error("fail to invoke ", e);
catStatus = Transaction.FAIL;
isPushSuccess = false;
} finally {
try {
Cat.logTransaction(PaymentConstant.CAT_TYPE_TASK, catTypeName, executeStartTime, catStatus);
} catch (Exception e) {
LOGGER.error("fail to cat ", e);
}
}
if (isInvoked) {
break;
}
}
//4. 更新补偿日志的记录
if (isInvoked) {
if (isPushSuccess) {
logEntity.setIsSuccess(PaymentConstant.COMPENSATION_PUSH_SUCCESS);
} else {
logEntity.setIsSuccess(PaymentConstant.COMPENSATION_PUSH_FAILED);
}
logEntity.setPushCount(logEntity.getPushCount() + 1);
sendEmail(logEntity);
sendTextMessage(logEntity, catTypeName);
}
updateCompensationLogStatus(logEntity);
}
}
} catch (Exception e) {
LOGGER.error("fail to execute update compensation", e);
catStatus = Transaction.FAIL;
} finally {
isCompensationTaskRunning.compareAndSet(true, false);
try {
Cat.logTransaction(PaymentConstant.CAT_TYPE_TASK, PaymentConstant.CAT_NAME_COMPENSATION_LOG, startTime, catStatus);
} catch (Exception e) {
LOGGER.error("fail to cat log", e);
}
}
}
}
问题是:每次触发定时任务,成员变量没有重新初始化,沿用了上次任务赋的值,怎么会这样呢?