京東任務編排框架asyncTool源碼初探

京東的一個框架,可以像promise一樣 支持多線程順序執行,依賴執行 看了下文件規模,核心類就幾個非常適合我哈哈哈哈。讓我們來看看有啥神奇的地方吧

我們也可以從test模塊中看到,很貼心的給我們準備了樣例,從包名可以推出使用方法

  • 依賴
  • 新的依賴
  • 並行任務
  • 串行任務

進入 TestSequential 類,是怎麼運行的,從以下代碼可看出核心類是Iworker、Icallback、WorkerWrapper

public class TestSequential {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        SeqWorker w = new SeqWorker();
        SeqWorker1 w1 = new SeqWorker1();
        SeqWorker2 w2 = new SeqWorker2();

        //順序0-1-2
        WorkerWrapper<String, String> workerWrapper2 =  new WorkerWrapper.Builder<String, String>()
                .worker(w2)
                .callback(w2)
                .param("2")
                .build();

        WorkerWrapper<String, String> workerWrapper1 =  new WorkerWrapper.Builder<String, String>()
                .worker(w1)
                .callback(w1)
                .param("1")
                .next(workerWrapper2)
                .build();

        WorkerWrapper<String, String> workerWrapper =  new WorkerWrapper.Builder<String, String>()
                .worker(w)
                .callback(w)
                .param("0")
                .next(workerWrapper1)
                .build();

        testGroupTimeout(workerWrapper);
    
        }
        private static void testGroupTimeout(WorkerWrapper<String, String> workerWrapper) throws ExecutionException, InterruptedException {
            long now = SystemClock.now();
            System.out.println("begin-" + now);
        
            Async.beginWork(2500, workerWrapper);
        
            System.out.println("end-" + SystemClock.now());
            System.err.println("cost-" + (SystemClock.now() - now));
        
            Async.shutDown();
        }
    }
  1. 定義callback類,實現ICallback接口重寫result方法
  2. 定義work類,實現Iworker接口重寫,重寫action方法
  3. 定義WorkerWrapper,build模式將work、callback、入參傳入組裝。可以指定next爲其他的WorkerWrapper,形成鏈條,供串行運行
  4. 使用Async.beginWork(2500, workerWrapper);啓動, Async.shutDown()來結束異步線程。

整個系統的入口就在Async#beginWork方法上了

public static boolean beginWork(long timeout, ThreadPoolExecutor pool, List<WorkerWrapper> workerWrappers) throws ExecutionException, InterruptedException {
    if(workerWrappers == null || workerWrappers.size() == 0) {
        return false;
    }
    //定義一個map,存放所有的wrapper,key爲wrapper的唯一id,value是該wrapper,可以從value中獲取wrapper的result
    Map<String, WorkerWrapper> forParamUseWrappers = new ConcurrentHashMap<>();
    // 核心實現使用CompletableFuture
    CompletableFuture[] futures = new CompletableFuture[workerWrappers.size()];
    for (int i = 0; i < workerWrappers.size(); i++) {
        WorkerWrapper wrapper = workerWrappers.get(i);
        // 追溯源碼時還在想爲啥把pool一層層往work方法裏傳,原來是個CompletableFuture#runAsync方法使用的。真是精妙
        futures[i] = CompletableFuture.runAsync(() -> wrapper.work(pool, timeout, forParamUseWrappers), pool);
    }
    try {
        CompletableFuture.allOf(futures).get(timeout, TimeUnit.MILLISECONDS);
        return true;
    } catch (TimeoutException e) {
        Set<WorkerWrapper> set = new HashSet<>();
        totalWorkers(workerWrappers, set);
        for (WorkerWrapper wrapper : set) {
            wrapper.stopNow();
        }
        return false;
    }
}

其中這個pool是一個靜態變量,可以根據自己的需求來調整線程數量。

public static final ThreadPoolExecutor COMMON_POOL =
        new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, 1024,
                15L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                (ThreadFactory) Thread::new);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章