quartz多次觸發定時任務時成員變數未初始化
阿新 • • 發佈:2018-12-09
專案中遇到一個問題:每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);
}
}
}
}
問題是:每次觸發定時任務,成員變數沒有重新初始化,沿用了上次任務賦的值,怎麼會這樣呢?