网上找了下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);
}