Home
img of docs

将介绍 CompletableFuture 在 Java 中如何简化线程处理,通过异步编程模型提升代码的可读性与性能

chou403

/ Thread

/ c:

/ u:

/ 4 min read


supplyAsync

用来开启异步任务。

   public static void main(String[] args) {
    SmallTool.print("小白进入餐厅");
    SmallTool.print("小白点了菜");
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("厨师炒菜");
        SmallTool.sleep(200);
        SmallTool.print("厨师打饭");
        SmallTool.sleep(100);
        return "菜 做好了";
    });

    SmallTool.print("小白在打游戏");
    // join() 会等待任务执行结束,然后返回任务的结果
    SmallTool.print(String.format("%s,小白开吃", cf.join()));
}

thenCompose

把前面任务的结果交给下一个异步任务。

   public static void main(String[] args) {
    SmallTool.print("小白进入餐厅");
    SmallTool.print("小白点了菜 + 米饭");
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("厨师炒菜");
        SmallTool.sleep(200);
        return "菜";
    }).thenCompose(dish -> CompletableFuture.supplyAsync(() -> {
        SmallTool.print("服务员打饭");
        SmallTool.sleep(100);
        return dish + " + 米饭";
    }));

    SmallTool.print("小白在打游戏");
    // join() 会等待任务执行结束,然后返回任务的结果
    SmallTool.print(String.format("%s,小白开吃", cf.join()));
}

thenConbine

等待两个任务都执行完,得到两个结果,再把两个加工成一个结果。

   public static void main(String[] args) {
    SmallTool.print("小白进入餐厅");
    SmallTool.print("小白点了菜 + 米饭");
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("厨师炒菜");
        SmallTool.sleep(200);
        return "菜";
    }).thenCombine(CompletableFuture.supplyAsync(() -> {
        SmallTool.print("服务员蒸饭");
        SmallTool.sleep(300);
        return "米饭";
    }), (dish, rice) -> {
        SmallTool.print("服务员打饭");
        SmallTool.sleep(100);
        return String.format("%s + %s 好了", dish, rice);
    });

    SmallTool.print("小白在打游戏");
    SmallTool.print(String.format("%s,小白开吃", cf.join()));
}

applyToEither

上个任务和这个任务一起运行,哪个先运行完成,就把哪个任务结果交个function。

   public static void main(String[] args) {
    SmallTool.print("张三走出餐厅,来到公交站");
    SmallTool.print("等待 700路 或者 800路 公交到来");
    CompletableFuture<String> bus = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("700路公交正在赶来");
        SmallTool.sleep(300);
        return "700路到了";
    }).applyToEither(CompletableFuture.supplyAsync(() -> {
        SmallTool.print("800路公交正在赶来");
        SmallTool.sleep(200);
        return "800路到了";
    }), firstComeBus -> firstComeBus);

    SmallTool.print(String.format("%s,小白坐车回家", bus.join()));
}

thenApply

把前面异步任务的结果,交给后面的function,一个线程操作。

   public static void main(String[] args) {
    SmallTool.print("小白吃好了");
    SmallTool.print("小白 结账,要求开发票");
    CompletableFuture<String> invoice = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("服务员收款 500元");
        SmallTool.sleep(200);
        return "500";
    }).thenApply(money -> {
        SmallTool.print(String.format("服务员开发票 面额 %s元", money));
        SmallTool.sleep(200);
        return String.format("%s元发票", money);
    });

    SmallTool.print("小白 街道朋友的电话,想一起打游戏");
    SmallTool.print(String.format("小白拿到%s,准备回家", invoice.join()));
}

thenApplyAsync

把前面异步任务的结果,交给后面的function,两个线程操作,若线程一样(线程复用)。

   public static void main(String[] args) {
    SmallTool.print("小白吃好了");
    SmallTool.print("小白 结账,要求开发票");
    CompletableFuture<String> invoice = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("服务员收款 500元");
        SmallTool.sleep(300);
        return "500";
    }).thenApplyAsync(money -> {
        SmallTool.print(String.format("服务员开发票 面额 %s元", money));
        SmallTool.sleep(200);
        return String.format("%s元发票", money);
    });

    SmallTool.print("小白 街道朋友的电话,想一起打游戏");
    SmallTool.print(String.format("小白拿到%s,准备回家", invoice.join()));
}

exceptionally

处理异常情况,链路上面的任何一个任务抛出异常,都会调用。

   public static void main(String[] args) {
    SmallTool.print("张三走出餐厅,来到公交站");
    SmallTool.print("等待 700路 或者 800路 公交到来");
    CompletableFuture<String> bus = CompletableFuture.supplyAsync(() -> {
        SmallTool.print("700路公交正在赶来");
        SmallTool.sleep(100);
        return "700路到了";
    }).applyToEither(CompletableFuture.supplyAsync(() -> {
        SmallTool.print("800路公交正在赶来");
        SmallTool.sleep(200);
        return "800路到了";
    }), firstComeBus -> {
        SmallTool.print(firstComeBus);
        if (firstComeBus.startsWith("700")) {
            throw new RuntimeException("撞树了。。。");
        }
        return firstComeBus;
    }).exceptionally(e -> {
        SmallTool.print(e.getMessage());
        SmallTool.print("小白叫出租车");
        return "出租车 叫到了";
    });

    SmallTool.print(String.format("%s,小白坐车回家", bus.join()));
}