网上找了下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()里的异常会被存在返回值中。