java 个性化定时任务schedule实现

1.java个性化定时任务工具类

import java.util.concurrent.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RetryScheduler {

	private static final ConcurrentMap<String, RetryTask> TASKS = new ConcurrentHashMap<String, RetryTask>();

	private static final int EXE_THREAD_COUNT = 3;

	private static ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 10, 50L, TimeUnit.MILLISECONDS,
			new LinkedBlockingQueue<Runnable>(100));

	private static final int DEFAULT_DELAY = 3;

	private static final int DEFAULT_INTERVAL = 3;

	private static final int DEFAULT_RETRY_COUNT = 3;

	// api
	public static void schedule(String id, Runnable task) {
		schedule(id, task, DEFAULT_DELAY, DEFAULT_INTERVAL, DEFAULT_RETRY_COUNT);
	}

	public static void schedule(String id, Runnable task, int retryDelay, int interval, int retryCount) {
		RetryTask rtask = new RetryTask(id, task, retryDelay, interval, retryCount);
		if (retryDelay == 0) {
			executor.submit(rtask);
		}
		TASKS.put(id, rtask);
	}

	public static void cancel(String id) {
		RetryTask task = TASKS.get(id);
		if (task != null) {
			task.cancel();
		}
	}

	//
	static {
		ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
		executorService.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				for (RetryTask rtask : TASKS.values()) {
					if (rtask.isDone()) {
						rtask.cancel();
						continue;
					}
					if (rtask.isTimeout()) {
						rtask.updateNextExpire();
						executor.submit(rtask);
					}
				}
			}
		}, 0, 1000, TimeUnit.MILLISECONDS);
	}

	static class RetryTask implements Runnable {

		private Logger logger = LoggerFactory.getLogger(getClass());

		// 最长执行时间
		private static final long MAX_EXECUTE_TIME = 1000 * 60 * 10;

		// 唯一标识
		private String id;

		private Runnable task;

		//
		private long deadLine;

		// 上次重试完成时间
		private long nextExpire;

		// 重试间隔(单位毫秒)
		private int interval;

		// 已经重试完成次数
		private volatile int exeCount;

		// 最多重试次数
		private int retryCount;

		//
		private int errCount;

		public RetryTask(String id, Runnable task, int retryDelay, int interval, int retryCount) {
			super();
			this.id = id;
			this.task = task;
			this.nextExpire = System.currentTimeMillis() + (retryDelay + interval) * 1000;
			this.interval = interval * 1000;
			this.retryCount = retryCount;

			// max execute time 10 minutes
			deadLine = System.currentTimeMillis() + MAX_EXECUTE_TIME;
		}

		public void cancel() {
			logger.info(id + "  cancel");
			TASKS.remove(id);
		}

		public boolean isDone() {
			return (exeCount >= retryCount) || (errCount > 3) || isDead();
		}

		public boolean isTimeout() {
			return System.currentTimeMillis() > nextExpire;
		}

		private void updateNextExpire() {
			nextExpire += interval;
		}

		private boolean isDead() {
			return (System.currentTimeMillis() > deadLine);
		}

		@Override
		public void run() {
			if (isDone()) {
				cancel();
				return;
			}
			logger.info("id={} timeout start retry index={} interval={} totalCount={}", id, exeCount + 1, interval, retryCount);
			long start = System.currentTimeMillis();
			try {
				task.run();
			} catch (Throwable e) {
				logger.error(e.getMessage(), e);
				++errCount;
			} finally {
				int costTime = (int) (System.currentTimeMillis() - start);
				if (costTime > interval) {
					interval = costTime;
				}
				++exeCount;
			}
		}
	}

}

2.按key创建定时任务和取消任务

StringBuilder sequenceSb = new StringBuilder("testkey_").append(id).append("_");
        RetryScheduler.schedule(sequenceSb.toString(), new Runnable() {
            @Override
            public void run() {
            	//判断是不是需要重复
            	String stateKey = new StringBuilder(sequenceSb).append("_state").toString();
        		String state = redisCache.get(stateKey);
                if(state != null){
                	if("0".equals(state)) {
                		//如果发送成功取消定时任务
                		RetryScheduler.cancel(sequenceSb.toString());
                	}else if("-1".equals(state)) {
                		//没有成功继续执行
                	}
                }
            }
        }, 0, 5, 100);//每隔5s执行一次,最多执行100次
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值