Jdk8 CompletableFuture提供了新的异步编程思路,可以对多个异步处理进行编排,实现更复杂的异步处理。其内部使用ForkJoinPool实现异步,使用CompletableFuture可以把回调的实现改为同步调用实现。CompletableFuture提供了50多个API,现在分为场景来做介绍:
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f1");
return "f1";
});
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f2");
return "f2";
});
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f3");
return "f3";
});
CompletableFuture.allOf(f1, f2, f3).thenApply((Integer) -> {
try {
System.out.println(Thread.currentThread() + f1.get());
System.out.println(Thread.currentThread() + f2.get());
System.out.println(Thread.currentThread() + f3.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return 1;
});
System.out.println(Thread.currentThread() + " end");
执行结果:
hread[ForkJoinPool.commonPool-worker-1,5,main]-f1
Thread[ForkJoinPool.commonPool-worker-1,5,main]-f2
Thread[ForkJoinPool.commonPool-worker-2,5,main]-f3
Thread[main,5,main]f1
Thread[main,5,main]f2
Thread[main,5,main]f3
Thread[main,5,main] end
对于这种场景,实际上也可以使用CountDownLatch来解决。
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f1");
return "f1";
});
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f2");
return "f2";
});
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f3");
return "f3";
});
CompletableFuture.allOf(f1, f2, f3).thenApplyAsync((Integer) -> {
try {
System.out.println(Thread.currentThread() + f1.get());
System.out.println(Thread.currentThread() + f2.get());
System.out.println(Thread.currentThread() + f3.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return 1;
});
System.out.println(Thread.currentThread() + " end");
执行结果:
Thread[ForkJoinPool.commonPool-worker-1,5,main]-f1
Thread[ForkJoinPool.commonPool-worker-1,5,main]-f2
Thread[ForkJoinPool.commonPool-worker-2,5,main]-f3
Thread[main,5,main] end
Thread[ForkJoinPool.commonPool-worker-2,5,main]f1
Thread[ForkJoinPool.commonPool-worker-2,5,main]f2
Thread[ForkJoinPool.commonPool-worker-2,5,main]f3
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f1");
return "f1";
});
CompletableFuture<String> f2 = f1.thenApplyAsync((v) -> {
System.out.println(Thread.currentThread() + "-f2");
return "f2";
});
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + "-f3");
return "f3";
});
f2.thenCombineAsync(f3, (f2s, f3s) -> {
System.out.println(Thread.currentThread() + f2s);
System.out.println(Thread.currentThread() + f3s);
return null;
});
System.out.println(Thread.currentThread() + " end");
ThreadPoolTaskExecutor是一个spring的线程池技术,它是使用jdk中的java.util.concurrent.ThreadPoolExecutor进行实现。
delegate = new org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor();
// 核心数
delegate.setCorePoolSize(Runtime.getRuntime().availableProcessors());
// 线程池数
delegate.setMaxPoolSize(Runtime.getRuntime().availableProcessors() + 10);
// 队列数
delegate.setQueueCapacity(1000);
// 等待实际
delegate.setKeepAliveSeconds(300);
// 拒绝策略
delegate.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
//
delegate.setTaskDecorator(new ContextCopyingDecorator());
delegate.initialize();
// taskDecorator主要是对Runnable任务装饰一下, 在任务执行时完成异常日志打印、ThreadLocal清理等功能
static class ContextCopyingDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
User user = AppContext.getCurrentUser();
return () -> {
try {
AppContext.clearThreadContext();
AppContext.putThreadContext(GlobalNames.SESSION_CONTEXT_USERINFO_KEY, user);
runnable.run();
} finally {
AppContext.clearThreadContext();
}
};
}
}
依托TaskDecorator可以实现线程信息信息共享:比如当前用户信息,时区信息,完成异常日志打印、ThreadLocal清理等功能,所以在使用CompletableFuture的时候结合TaskDecorator可以让使用者无感知的切换为异步或者同步方式。