最近在工作中使用到了spring自带的@Async,主要是为了把其中耗时多、响应慢、计算复杂的业务抽出来查询。从代码设计上看Spring自带的比传统线程池提交在代码层次上看起来优雅简洁了不少,无需显示去申明线程池相关代码, 在方法上加注解既可异步返回结果。空闲时间大概看了下原理,其实就是代理模式(cglib or 接口), 刚好最近学习到线程和并发相关的jdk组件,今天就打算自己手动实现这个异步组件。
总体实现思路流程:客户端调用后-》通过代理模式代理-》重写Submit方法并返回Future-》把Future 放到自定义的异步返回包装类-》客户端直接拿到返回的Future 进行阻塞get
流程图:
以下是接口代理实现,至于Cglib代理实现和接口代理原理是一致的,可以自行实现。
1.新建代理接口
public interface IAsyncProxy { /** * 获取代理对象 * 1. 如果是实现了接口,默认使用 dynamic proxy 即可。 * 2. 如果没有实现接口,默认使用 CGLIB 实现代理。 * @return 代理对象 */ Object proxy(); }
2.新建动态代理实现类
public class DynamicProxy implements InvocationHandler, IAsyncProxy { /** * 被代理的对象 */ private final Object target; public DynamicProxy(Object target) { this.target = target; } /** * * * @param proxy 原始对象 * @param method 方法 * @param args 入参 * @return 结果 * @throws Throwable 异常 */ @Override @SuppressWarnings("all") public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return AsyncExecutor.submit(target, method, args); } @Override public Object proxy() { // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler handler = new DynamicProxy(target); return Proxy.newProxyInstance(handler.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); } }
其中最主要的是代理之后我们要如何交给异步处理,在invoke方法内,我通过线程池去提交任务,细心的可以发现AsyncExecutor在jdk包里是没有的,这个类是我自己定义的。至于原因有以下几个:
1.jdk自带的ExecutorService的submit无法满足现有功能, 所以需要重新实现ExecutorService做扩展,重写submit方法。
2.submit之后需要包装统一的返回结果
3.定义异步接口
/** * <p> 异步执行结果 </p> / public interface IAsyncResult<T> extends Future<T> { /** * 获取执行的结果 * @return 结果 */ Object getResult(); }
抽象的异步返回类
public abstract class AbstractAsyncResult<T> implements IAsyncResult<T> { @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return false; } @Override public T get() throws InterruptedException, ExecutionException { try { return this.get(AsyncConstant.DEFAULT_TIME_OUT, TimeUnit.SECONDS); } catch (TimeoutException e) { throw new RuntimeException(e); } } }
返回结果类
/** * 异步执行结果 */ public class AsyncResult<T> extends AbstractAsyncResult<T> { /** * future 信息 */ private Future<T> future; /** * 结果 */ private Object value; /** * 获取执行的结果 * @return 结果 */ @Override public Object getResult() { // 直接返回结果 if(future == null) { return this.getValue(); } try { T t = future.get(); // 这里拿到的 AsyncResult 对象 if(null != t) { return ((AsyncResult)t).getValue(); } return null; } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } } @Override public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return future.get(timeout, unit); } public Object getValue() { return this.value; } public void setValue(Object value) { this.value = value; } public void setFuture(Future<T> future) { this.future = future; } }
4.定义一个异步接口,继承ExecutorService
/** * <p> 异步框架执行器 </p> */ public interface IAsyncExecutor extends ExecutorService { }
/** * 异步执行器 */ public class AsyncExecutor extends ThreadPoolExecutor implements IAsyncExecutor { //region 私有属性 /** * 是否初始化 */ private static volatile boolean isInit = false; /** * 是否被销毁 */ private static volatile boolean isDestroy = false; /** * 线程执行器 */ private static ExecutorService executorService = null; //endregion //region 构造器 public AsyncExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } public AsyncExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); } public AsyncExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); } public AsyncExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); } //endregion @SuppressWarnings("all") public static <T> IAsyncResult<T> submit(Object target, Method method, Object[] objects) { // 初始化的判断 if(!isInit) { init(); } //通过线程池提交 Future future = executorService.submit(new Runnable() { @Override public void run() { try { method.invoke(target, objects); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); //Future future = executorService.submit(() -> method.invoke(target, objects)); AsyncResult<T> asyncResult = new AsyncResult<>(); asyncResult.setFuture(future); return asyncResult; } /** * 初始化 * 1. 暂时不添加配置相关的信息 * 2. 最后调整状态 */ private static synchronized void init() { try { if(isInit) { return; } // 各种属性配置 // 淘汰策略 // 最佳线程数量 executorService = Executors.newFixedThreadPool(10); updateExecutorStatus(true); } catch (Exception e) { throw new AsyncRuntimeException(e); } } /** * 销毁容器 * 1. 销毁的时候进行等待,确保任务的正常执行完成。 * 2. 任务执行的统计信息,后期添加。 */ private static synchronized void destroy() { if(isDestroy) { return; } executorService = null; updateExecutorStatus(false); } /** * 更新执行器的状态 * @param initStatus 初始化状态 */ private static void updateExecutorStatus(final boolean initStatus) { isInit = initStatus; isDestroy = !isInit; } }
总结:
以上代码最核心的就是通过动态代理在内部通过线程池异步提交,以及重写jdk的线程池也是为了能够重写内部核心方法