可激活的间隔任务执行器

近来做项目,遇到一个很蛋疼的问题。以前早就遇到过,但是由于以前系统有变通的方法解决,也就没再弄这个事情。

什么问题呢 ? 就是一般情况下,系统会执行以下有时间间隔的周期性任务(比如,每小时执行一次垃圾数据的清理工作),但是,遇到特殊情况还要临时激活任务,让任务临时执行一下(比如突发性垃圾数据猛增)。

对于带有时间间隔的周期性任务,写个执行器应该是一件很容易的事情。开启一个线程,每次执行完任务就sleep一个时间间隔,这样往复循环下去,就可以了。

基于上述思路,列举部分代码如下:

package houlei.support.util.task;

/**
 * 间隔执行的周期任务
 */
public interface DelayTask extends CycleTask{

	/**
	 * 调度任务的时间间隔
	 */
	long getDelay();
	
}

上述的是一个接口类,它有父接口,有execute方法,用于执行任务内容;有getDelay方法,用于获取执行任务的时间间隔。

package houlei.support.util.task;

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

import houlei.support.lang.ErrorHandler;

/**
 * 可激活的间隔任务执行器。只执行间隔执行的周期任务。
 * <p>主要执行间隔任务,当任务处于休眠期时,可通过调用{@link #active()}方法,唤醒执行器,激活当前任务。</p>
 */
public class ActivableDelayTaskWorker {

	private static final Logger LOG = LoggerFactory.getLogger(ActivableDelayTaskWorker.class);
	
	private ErrorHandler errorHandler = new ErrorHandler() {
		public void doHandler(Throwable throwable, String s) {
			LOG.error(s, throwable);
		}
	};
	
	private DelayTask delayTask;
	private Worker worker;
	private String name;
	private volatile boolean busy = false;
	
	/**
	 * 执行器线程
	 */
	private class Worker extends Thread{
		public Worker() {
			super(name);
		}
		private volatile boolean running = false;
		public void run(){
			LOG.info("线程["+Thread.currentThread().getName()+"]开始运行。");
			while(running){
				try {
					busy = true;
					delayTask.execute();
					busy = false;
					try {
						synchronized (worker) {
							worker.wait(delayTask.getDelay());
						}
					} catch (InterruptedException e) {
					}
				} catch (Throwable t) {
					errorHandler.doHandler(t, "任务["+name+"]在调用过程中出现异常。");
				}
			}
			LOG.info("线程["+Thread.currentThread().getName()+"]运行结束。");
		}
	}
	
	/**
	 * @param name 线程名称
	 * @param delayTask 周期任务的实例
	 */
	public ActivableDelayTaskWorker(String name, DelayTask delayTask) {
		if(name==null)throw new IllegalArgumentException("参数[name]不能为空");
		if(delayTask==null)throw new IllegalArgumentException("参数[delayTask]不能为空");
		this.name = name;this.delayTask = delayTask;
		worker = new Worker();
	}
	
	/**
	 * 唤醒执行器,激活当前任务。
	 */
	public void active(){
		if(busy)return;
		synchronized (worker) {
			worker.notify();
		}
	}
	
	/**
	 * 执行器的工作状况,是否处于任务调度阶段。
	 */
	public boolean isBusy() {
		return busy;
	}
	
	/**
	 * 开启调度线程
	 */
	public void startup(){
		if(!worker.running){
			worker.running = true;
			worker.start();
		}
	}
	
	/**
	 * 结束调度线程
	 */
	public void shutdown(){
		if(worker.running){
			worker.running = false;
			worker.interrupt();
			try {
				worker.join(5000);
			} catch (InterruptedException e) {
				errorHandler.doHandler(e, "任务["+name+"]无法在5秒内终止");
			}
		}
	}
	
	public void setErrorHandler(ErrorHandler errorHandler) {
		this.errorHandler = errorHandler;
	}
	
	public ErrorHandler getErrorHandler() {
		return errorHandler;
	}
	public DelayTask getDelayTask() {
		return delayTask;
	}
	public String getName() {
		return name;
	}
}

这个就是执行器类了。当然,这个代码的质量不算高,因为,一个线程只能执行一个任务;线程的大部分时间都是在等待周期的到来。


但是,功能还是实现了。某些特定场景还是必须要用到的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值