配合长时间定时任务,立即执行该定时任务的思路

业务场景:

订单支付成功时,订单信息需要给银行系统同步,由于不能保证银行返回信息的时间,所以使用队列进行同步,并且用spring的定时任务执行。

需求:

订单支付成功时立即执行一次同步任务,如果失败,则没半小时执行一次同步任务,直至同步成功。

问题:

spring定时任务定为半小时,订单成功支付时,无法立即执行任务,只能等0-30分钟后执行同步任务,所以需要做一个功能,在订单支付成功的时候,调用一次同步任务。

解决方案:

在服务启动时,初始化一个A线程,该线程每隔N秒扫描一次任务集合,集合中存放着某个任务,扫描到就执行任务。然后在订单支付成功时,在将订单放入队列后,接着将订单放入任务集合,由A线程扫描并执行。


支付成功后代码:

BizLogger.info("订单支付成功!!!");
Singleton.put(SpdbRateTask.class);

Singleton:

import java.util.concurrent.ConcurrentHashMap;

public class Singleton {
	private static ConcurrentHashMap<String,Class> map = new ConcurrentHashMap<String,Class>();
	public static ConcurrentHashMap<String,Class> getMap(){
		return map;
	}
	
	public static void put(Class clazz){
		map.put(clazz.getCanonicalName(), clazz);
	}
}

初始化线程任务:

import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.jniu.app.task.ExcutTask;
import com.jniu.app.util.Singleton;
import com.jniu.bas.context.Context;
import com.jniu.bas.log4j.logger.BizLogger;

public class ProjectInit implements ServletContextListener {
	private ConcurrentHashMap<String, Class> map = Singleton.getMap();

	/**
	 * 初始化学校缓存
	 */
	@Override
	public void contextInitialized(final ServletContextEvent sce) {
		// 初始化当前上下文
        Context ctx = Context.createContext("currentContext", null);
        Context.pushCurrentContext(ctx);
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				Iterator<Map.Entry<String, Class>> it = map.entrySet().iterator();
				ExcutTask t = null;
				try {
					Thread.sleep(3000);//任务不多,且不是很频繁,队列使用的是redis的list,为了防止定时任务执行时redis中还没有数据,这里延迟三秒
					while (it.hasNext()) {
						Map.Entry<String, Class> entry = it.next();
						BizLogger.info("项目任务"+entry.getValue().getCanonicalName()+"执行开始");
						t = ((ExcutTask) WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(entry.getValue()));
						t.a();
						BizLogger.info("项目任务"+t.getClass().getCanonicalName()+"执行完成");
						it.remove();
					}
				} catch (Exception e) {
					e.printStackTrace();
					BizLogger.info("项目任务"+t.getClass().getCanonicalName()+"执行失败");
				}
			}
		};
		Timer timer = new Timer();
		long delay = 0;
		long intevalPeriod = 10 * 1000;//每十秒检查一遍任务集合
		timer.scheduleAtFixedRate(task, delay, intevalPeriod);
	}

	/**
	 * 销毁工作
	 */
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// TODO Auto-generated method stub
	}
}

spring定时任务:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.jniu.app.constans.Constans;
import com.jniu.app.service.SpdbOrderService;
import com.jniu.bas.log4j.logger.BizLogger;
import com.jniu.bas.result.ResultBean;

@Service
public class SpdbRateTask implements ExcutTask{
	@Autowired
	RedisTemplate<String, Object> redisTemplate;
	@Autowired
	SpdbOrderService spdbOrderService;
	
	public void a(){
		String t = null;
		ResultBean resultBean = null;
		try {
			long size = redisTemplate.opsForList().size(Constans.SPDB_RATE_QUEUE);
			if(size>0){
				for(int i=0;i<size;i++){
					t = (String)redisTemplate.opsForList().rightPop(Constans.SPDB_RATE_QUEUE);
					if(t!=null){
						resultBean = spdbOrderService.transDetailObtain(t);
						if(!resultBean.isSuccess()){
							redisTemplate.opsForList().leftPush(Constans.SPDB_RATE_QUEUE, t);
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			if(t!=null)
				redisTemplate.opsForList().leftPush(Constans.SPDB_RATE_QUEUE, t);
			BizLogger.info(resultBean.getMessage());
		}
	}

	@Override
	public String toString() {
		return "SpdbRateTask-----name";
	}
}





  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值