背景
在以前coding的时候,有时会些异步代码,大多数情况下都是为了把不是立刻需要的数据单独处理,以提供相应速度。当然还有人多开些线程来提高运算效率,但是在本中主要关注解决的是异步的问题。
原理
异步工具类就是在系统启动时候先初始化一个符合参数自己工作环境的线程池,所有的异步操作占用的线程都是从这个线程池中获取的,这样能进行资源统一管理,不会因为异步操作而占用过多的服务器资源。
实现
- 异步工具类,AsyncService.java:
public class AsyncService {
private static final ExecutorService service = Executors.newFixedThreadPool(10);
// 也许没有必要这么做的
// static {
// Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
// @Override
// public void run() {
// if (service != null && !service.isShutdown()) {
// service.shutdown();
// }
// }
// }));
// }
/*
执行异步调用
@param obj 要调用的实例化对象
@param methodName 方法名
*/
public static void call(Object obj, String methodName) {
call(obj, methodName, null);
}
/**
执行异步调用
@param obj 要调用的实例化对象
@param methodName 方法名
@param paraTypes 参数类型
*/
public static void call(Object obj, String methodName, Class[] paraTypes) {
call(obj, methodName, paraTypes, null);
}
/**
执行异步调用
@param obj 要调用的实例化对象
@param methodName 方法名
@param paraTypes 参数类型
@param paraValues 参数值
*/
public static void call(Object obj, String methodName, Class[] paraTypes, Object[] paraValues) {
if (obj == null) {
throw new NullPointerException("Illegal parameter [obj is null]");
}
if (methodName == null || methodName.trim().isEmpty()) {
throw new NullPointerException("Illegal parameter [methodName is null or empty]");
}
service.submit(getRunnable(obj, methodName, paraTypes, paraValues));
}
/**
获取异步执行Runnable
@param obj 要调用的实例化对象
@param methodName 方法名
@param paraTypes 参数类型
@param paraValues 参数值
@return Runnabe
*/
private static Runnable getRunnable(final Object obj, final String methodName, final Class[] paraTypes, final Object[] paraValues) {
return new Runnable() {
@Override
public void run() {
try {
obj.getClass().getMethod(methodName, paraTypes).invoke(obj, paraValues);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
};
}
}
- 测试,Run.java:
public class Run {
public static void main(String[] args) {
Run run = new Run();
run.asyncCall();
}
private void asyncCall() {
for (int i = 0; i < 50; i++) {
AsyncService.call(this, "test");
AsyncService.call(this, "test", new Class[] {String.class}, new String[] {"test"});
}
}
public void test() {
System.out.println("This is a test!");
}
public void test(String msg) {
System.out.println(msg);
}
}
最后
这只是阐述了原理,不能直接拷贝到生产环境。为了方便,直接实例化了一个具有10个线程的固定线程池,在实际应用中一定是要根据自己的情况配置的。