京東的一個框架,可以像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();
}
}
- 定義callback類,實現ICallback接口重寫result方法
- 定義work類,實現Iworker接口重寫,重寫action方法
- 定義WorkerWrapper,build模式將work、callback、入參傳入組裝。可以指定next爲其他的WorkerWrapper,形成鏈條,供串行運行
- 使用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);