Java中实现优先级任务调度器

网上找了下java里的异步任务调度器,很多,但没有基于优先级队列的(或者我没发现),于是我写了一个。

前方干货预警!

一共四个文件。
AloneTask.java(带有优先级的任务类)
ComparableThreadPoolExecutor.java(带有比较器的线程池)
NamedThreadFactory.java(可命名线程池,这个不是必须的)
Scheduler.java(调度器,找了网上的一份改了下)

AloneTask这里加了很多项目里的东西,比如用了spring的依赖注入来获取任务类名,还有slf4j的日志工具,还有自己写的Util空判断器。遇上异常可以删掉那块或者留言,核心的地方不会有异常。

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

import org.slf4j.Logger;

public class AloneTask<T> implements Callable<T>, Comparable<AloneTask<T>>, Runnable {
	private static final Logger logger = Loggers.asyncLogger;

	Object service;
	String method;
	Object[] params;
	String trace;//调用任务的堆栈,性能较低,上线时注释 TODO
	int priority;

	public AloneTask(T service, String method, int priority, Object... params) {
		super();
		if (service instanceof String) {
			this.service = Config.ctx.getBean((String) service);
		} else {
			this.service = service;
		}
		this.priority = priority;
		this.method = method;
		this.params = params;
		this.trace = Util.getCallStack();
	}

	@Override
	@SuppressWarnings("unchecked")
	public T call() throws Exception {
		if (service == null || Util.isEmpty(method)) {
			logger.error("参数异常,无法完成任务.调用堆栈:" + this.trace);
			return null;
		}
		long startTime = System.currentTimeMillis();
		T future = (T) getMethod().invoke(this.service, this.params);
		long useTime = (startTime - System.currentTimeMillis()) / 1000;
		if (useTime > 10) {
			logger.warn("call cost time too long,time " + useTime + "s,task method:" + this.method);
		}
		return future;
	}
	
	@Override
	public void run() {
		if (service == null || Util.isEmpty(method)) {
			logger.error("参数异常,无法完成任务.调用堆栈:" + this.trace);
			return;
		}
		long startTime = System.currentTimeMillis();
		try {
			getMethod().invoke(this.service, this.params);
		} catch (Exception e) {
			logger.error("异步任务异常,任务所在线程:" + Thread.currentThread().getName() + " 异常详细信息:\n" + e.getMessage() + "\n任务调用堆栈:" + this.trace);
		}
		long useTime = (startTime - System.currentTimeMillis()) / 1000;
		if (useTime > 10) {
			logger.warn("call cost time too long,time " + useTime + "s,task method:" + this.method);
		}
	}

	/*
	 * 获取被调用的方法
	 */
	private Method getMethod() {
		Method m = null;
		try {
			Class<?>[] paramsClass = new Class[this.params.length];
			for (int i = 0; i < this.params.length; i++) {
				paramsClass[i] = this.params[i].getClass();
			}
			m = this.service.getClass().getDeclaredMethod(this.method, paramsClass);
		} catch (Exception e) {
			Method[] allMethods = this.service.getClass().getDeclaredMethods();
			for (Method mRec : allMethods) {
				if (mRec.getName().equals(this.method)) {
					Class<?>[] methodParamsTypes = mRec.getParameterTypes(); // 找到同名函数的参数类型
					if (methodParamsTypes.length == this.params.length) {
						boolean flag = true;
						for (int i = 0; i < methodParamsTypes.length; i++) {
							if (null != this.params[i]) {
								if (!match(this.params[i], methodParamsTypes[i])) {
									flag = false;
									break;
								}
							}
						}
						if (flag) {
							m = mRec;
							break;
						}
					}
				}
			}
		}

		if (null == m) {
			logger.info(String.format("未找到[%s]的[%s]方法完成任务.", this.service.getClass().toString(), this.method));
		} else {
			m.setAccessible(true);// 设置访问域以允许访问private和protected方法
		}
		return m;
	}

	/**
	 * 判断参数类型是否匹配
	 * 
	 * @param c
	 *            参数类型
	 * @param pc
	 *            方法参数类型
	 * @return
	 */
	private boolean match(Object p, Class<?> pc) {
		boolean isMatch = true;
		if (pc.isPrimitive()) { // 方法参数是基本类型
			if (!pc.equals(getPrimitiveClass(p.getClass()))) {
				isMatch = false;
			}
		} else {
			if (!pc.isInstance(p)) {
				isMatch = false;
			}
		}
		return isMatch;
	}

	private static Class<?> getPrimitiveClass(Class<?> c) {
		Class<?> pc = null;
		if (c.equals(Long.class)) {
			pc = long.class;
		} else if (c.equals(Integer.class)) {
			pc = int.class;
		} else if (c.equals(Double.class)) {
			pc = double.class;
		} else if (c.equals(Float.class)) {
			pc = float.class;
		} else if (c.equals(Short.class)) {
			pc = short.class;
		} else if (c.equals(Byte.class)) {
			pc = byte.class;
		} else if (c.equals(Character.class)) {
			pc = char.class;
		} else if (c.equals(Boolean.class)) {
			pc = boolean.class;
		}
		return pc;
	}

	//比较优先级
	@Override
	public int compareTo(AloneTask<T> o) {
		if (this.priority < o.priority) {
			return -1;
		}
		if (this.priority > o.priority) {
			return 1;
		}
		return 0;
	}
}

ComparableThreadPoolExecutor.java

public class ComparableThreadPoolExecutor extends ThreadPoolExecutor {

	public ComparableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
	}

	public ComparableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
	}

	public ComparableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
	}

	public ComparableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
	}

	@Override
	protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
		return new ComparableFutureTask<>(runnable, value);
	}

	@Override
	protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
		return new ComparableFutureTask<>(callable);
	}

	protected class ComparableFutureTask<V> extends FutureTask<V> implements Comparable<ComparableFutureTask<V>> {
		private Object object;

		public ComparableFutureTask(Callable<V> callable) {
			super(callable);
			object = callable;
		}

		public ComparableFutureTask(Runnable runnable, V result) {
			super(runnable, result);
			object = runnable;
		}

		@Override
		@SuppressWarnings({ "unchecked", "rawtypes" })
		public int compareTo(ComparableFutureTask<V> o) {
			if (this == o) {
				return 0;
			}
			if (o == null) {
				return -1; // 内容为null的任务排在队尾
			}
			if (object != null && o.object != null) {
				if (object.getClass().equals(o.object.getClass())) {
					if (object instanceof Comparable) {
						return ((Comparable) object).compareTo(o.object);
					}
				}
			}
			return 0;
		}
	}
}

NamedThreadFactory.java 给线程起个名字方便debug和管理。

public class NamedThreadFactory implements ThreadFactory {
	
	private AtomicInteger order = new AtomicInteger(0);
	
	private String name;
	
	public NamedThreadFactory(String name) {
		this.name = name;
	}

	@Override
	public Thread newThread(Runnable r) {
		Thread thread = new Thread(r);
		thread.setName(name + "  ORDER:" + order.getAndIncrement());
		return thread;
	}
	
}

Scheduler.java,我预先放了5个优先级,可以外部定义(记得改ComparableThreadPoolExecutor的compareTo)。

public class Scheduler {
	private static final Scheduler instance = new Scheduler();
	private static ExecutorService executorServie;
	
	private static final int CORE_POOL_SIZE = 10;
	private static final int MAXIMUM_POOL_SIZE = 10;

	private Scheduler() {
		executorServie = new ComparableThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 1, 
														  TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>(),
														  new NamedThreadFactory("Scheduler任务调度器子线程"));
	}

	@Bean(name = "Bmall.Scheduler", initMethod = "init", destroyMethod = "shutdown")
	public static Scheduler getInstance() {
		return instance;
	}
	
	public void init() {
		
	}

	public void shutdown() {  
		executorServie.shutdown();
    }

	/**
	 * 将任务存入任务队列中。支持存private和protected方法。
	 * @param service 类名(必须注册为spring的bean)或其实例
	 * @param method 方法名
	 * @param priority 优先级
	 * @param params 参数
	 */
	@SuppressWarnings("unchecked")
	public <T> void call(T service, String method, PRIORITY priority, T... params) {
		Runnable runnable = new AloneTask<T>(service, method, priority.getValue(), params);
		executorServie.execute(runnable);
	}
	
	/**
	 * 将任务存入任务队列中并返回future。支持存private和protected方法。
	 * @param service 类名(必须注册为spring的bean)或其实例
	 * @param method 方法名
	 * @param priority 优先级
	 * @param params 参数
	 * @return future可用于回调
	 */
	@SuppressWarnings("unchecked")
	public <T> Future<T> callBack(T service, String method, PRIORITY priority, T... params){
		Callable<T> callback = new AloneTask<T>(service, method, priority.getValue(), params);
		Future<T> future = executorServie.submit(callback);
		return future;
	}
	
	public enum PRIORITY {
		/** 最低级别 */
		LOWEST(5),
		
		/** 需要一段时间后执行的级别 */
		LOW(4),
		
		/** 默认级别*/
		NORMAL(3),
		
		/** 很可能马上就需要执行的级别 */
		HIGH(2),
		
		/** 需要立即执行的级别*/
		HIGHEST(1);
		
		private final int value;

	    // 构造器默认也只能是private, 从而保证构造函数只能在内部使用
	    private PRIORITY(int value) {
	        this.value = value;
	    }

	    public int getValue() {
	        return value;
	    }
	}

}

具体使用方法:(将print任务以中优先级放入队列中执行)

public void print(String str) {
	System.out.println(str);
}

public static void main(String[] args) {
	Scheduler.getInstance().call(this, "print", PRIORITY.NORMAL, "打印的内容");
}

需要注意的是Scheduler里的call()方法的异常会直接打印,而callback()里的异常会被存在返回值中。

你可能感兴趣的:(Java中实现优先级任务调度器)