最近在工作中使用到了spring自帶的Async,主要是爲了把其中耗時多、響應慢、計算複雜的業務抽取幾個模塊出來,並行查詢。不得不說spring自帶的比傳統線程池提交在代碼層次上看起來優雅簡潔了不少,直接返回一個AsyncResult,然後調用方通過Future接收。今天就打算自己手動實現這個異步組件,並藉此學習其中的原理。先思考一個問題,爲什麼直接調用一個普通的方法就能實現異步?第一個想到的就是代理,所以本章就從代理模式出發。
總體實現思路流程:客戶端調用後-》通過代理模式代理-》重寫Submit方法並返回Future-》把Future 放到自定義的異步返回包裝類-》客戶端直接拿到返回的Future 進行get。
1.新建代理接口
public interface IAsyncProxy { /** * 獲取代理對象 * 1. 如果是實現了接口,默認使用 dynamic proxy 即可。 * 2. 如果沒有實現接口,默認使用 CGLIB 實現代理。 * @return 代理對象 */ Object proxy(); }
由於代理分2種,接口的代理還有無接口的代理,所以這裏定義成接口方便擴展。
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); } }
由於篇幅有限,這裏只講動態代理,至於Cglib代理實現方案和接口代理原理是一致的。最終要的是代理之後我們要如何交給異步處理,所以在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 { }
package com.github.houbb.async.core.executor; import java.util.concurrent.*; /** * 異步執行器 */ 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; } }