这篇“Java多线程开发工具之CompletableFuture怎么应用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java多线程开发工具之CompletableFuture怎么应用”文章吧。
Single Dog拿一个Appointment来举个列子,如下:
/** * 女神化完妆之后,还需要一小会选衣服,不过分吧。 * 也就是说我们现在有2个异步任务,第一个是化妆,第二个是选衣服。 * 选衣服要在化妆完成之后进行,这两个任务是串行 */ public static void main(String[] args) { // 线程池我前面的文章聊过,怎么配置可以去了解一下 ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); //任务1 CompletableFuture<String> makeUpFuture = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "-女神,开始化妆了"); try { // 化妆的时间 TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } return "化妆完毕了。"; }, threadPool); //任务2,makeUp是调用方,意思是makeUpFuture执行完后再执行 CompletableFuture<String> dressFuture = makeUpFuture.thenApply((result) -> { System.out.println(Thread.currentThread().getName() + "-女神" + result + "我开始选衣服啦,好了叫你!"); try { // 换衣服的时间 TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } return result + "衣服也选好了,走出去玩吧!"; }); dressFuture.thenAccept((result) -> { System.out.println(Thread.currentThread().getName() + "-" + result); }); }
上面的2个任务也可以理解为我们开发中要实现的不同功能,看明白前面的列子了吧?用它来写多线程运用的多丝滑。那我们就先讲一下它的核心的静态的方法,推荐用它的静态方法不要直接new对象。
1:无返回值的静态方法:
public static CompletableFuture<Void> runAsync(Runnable runnable)。
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) 。
上面一个2个方法,如果没有指定Executor就使用默认的ForkJoinPool.commonPool()线程池,如果指定线程池就使用指定的。
2:有返回值的方法
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
如果开始的代码你还看不懂那介绍了上面的几个方法就先小试牛刀一下:
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); CompletableFuture.runAsync(() -> { System.out.println(Thread.currentThread().getName()); int i = 10 / 2; System.out.println("运行的结果是:" + i); }, threadPool); CompletableFuture future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } return "Hello World"; }, threadPool); System.out.println(future.get());
好了讲过它的使用方法了那我们就聊一下它的几个使用的场景,开发中这写场景应该会使用到。
1:执行任务 A,执行任务B,待任务B执行完成后,用B的返回值区执行任务C。
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("执行任务A"); return "任务A"; }, executor); CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> { System.out.println("执行任务B"); return "任务B"; }, executor); CompletableFuture<String> futurec = futureB.thenApply((b) -> { System.out.println("执行任务C"); System.out.println("参数:" + b); return "a"; }); System.out.println(futurec.get());
运行结果,注意我上面没说B一定要在A执行以后执行。
场景2:多个任务串联执行,下一个任务的执行依赖上一个任务的结果,每个任务都有输入和输出。
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); CompletableFuture futureA = CompletableFuture.supplyAsync(() -> "Hello", executor); CompletableFuture futureB = futureA.thenApply((a) -> a + " World"); CompletableFuture futureC = futureB.thenApply((b) -> b); System.out.println(futureC.join());
输出结果,开发中的经典场景输出:
场景3:thenCombineAsync 联合 futureA和futureB的返回结果,然后在返回相关的数据
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10, executor); CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> 20, executor); CompletableFuture futureC = futureA.thenCombineAsync(futureB, (r1, r2) -> { System.out.println("r1的值为:" + r1 + ":r2的值为:" + r2); return r1 + r2; }); System.out.println(futureC.get());
结果输出:
好了聊完几个场景那就写一个在开发中的经典运用。
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); System.out.println("start..."); CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> { System.out.println("查询商品信息1"); return "future1"; }, executor); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> { System.out.println("查询商品信息2"); return "future2"; }, executor); CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> { System.out.println("查询商品信息3"); return "future3"; }, executor); final CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(future1, future2, future3); voidCompletableFuture.get(); System.out.println("end...future1的结果:" + future1.get() + ",future2的结果:" + future2.get() + ",future3的结果:" + future3.get());
输出结果