CompletableFuture的使用
1、开启子线程并获取子线程结果
@Test public void test1() { SmallTool.printTimeAndThread("媳妇进入餐厅"); SmallTool.printTimeAndThread("媳妇点饭, 蛋炒饭 + 米饭"); CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("厨师炒菜"); SmallTool.sleepMillis(200); SmallTool.printTimeAndThread("厨师盛饭"); SmallTool.sleepMillis(200); return "饭做好了"; }); SmallTool.printTimeAndThread("媳妇在玩手机"); SmallTool.printTimeAndThread(String.format("%s, 媳妇开吃",future.join())); }
2、thenCompose:连接两个异步任务(第一个异步任务完成后执行第二个异步任务),返回一个新的CompletableFuture
@Test public void test2() { SmallTool.printTimeAndThread("媳妇进入餐厅"); SmallTool.printTimeAndThread("媳妇点饭, 蛋炒饭 + 米饭"); CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("厨师炒菜"); SmallTool.sleepMillis(200); return "饭做好了"; }).thenCompose(res -> CompletableFuture.supplyAsync(() -> { //厨师炒完菜服务员才端饭 SmallTool.printTimeAndThread(res); SmallTool.printTimeAndThread("服务员端饭"); SmallTool.sleepMillis(200); return "饭盛好了"; })); SmallTool.printTimeAndThread("媳妇在玩手机"); SmallTool.printTimeAndThread(String.format("%s, 媳妇开吃",future.join())); }
3、thenApply:连接两个异步任务(第一个异步任务完成后执行第二个异步任务),返回的是同一个CompletableFuture,但CompletableFuture的数据类型可以改变
@Test public void test22() { SmallTool.printTimeAndThread("媳妇进入餐厅"); SmallTool.printTimeAndThread("媳妇点饭, 蛋炒饭 + 米饭"); CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("厨师炒菜"); SmallTool.sleepMillis(200); return "1"; }).thenApply(s -> { return s.equals("1")?"饭做好了":"饭没做好"; }); SmallTool.printTimeAndThread("媳妇在玩手机"); SmallTool.printTimeAndThread(String.format("%s, 媳妇开吃",future.join())); }
4、thenCombine:两个异步任务并行执行
@Test public void test3() { SmallTool.printTimeAndThread("媳妇进入餐厅"); SmallTool.printTimeAndThread("媳妇点饭, 蛋炒饭 + 米饭"); CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("厨师炒菜"); SmallTool.sleepMillis(200); return "菜做好了"; }).thenCombine(CompletableFuture.supplyAsync(() -> { //炒菜和做饭同时进行 SmallTool.sleepMillis(200); return "米饭做好了"; }), (r1, r2) -> { SmallTool.printTimeAndThread("服务员端饭"); SmallTool.sleepMillis(200); return String.format("%s和%s做好了", r1, r2); }); SmallTool.printTimeAndThread("媳妇在玩手机"); SmallTool.printTimeAndThread(String.format("%s, 媳妇开吃",future.join())); }
5、appltToEither:两个异步任务只有有一个执行完毕。exceptionally:异步任务中发送异常时执行
@Test public void test5() { SmallTool.printTimeAndThread("小白吃完饭打车"); CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("700路公交车来了"); SmallTool.sleepMillis(200); return "700路公交"; }).applyToEither(CompletableFuture.supplyAsync(() -> { SmallTool.printTimeAndThread("800路公交车来了"); SmallTool.sleepMillis(200); return "800路公交"; }), firstComeBus -> { if(firstComeBus.startsWith("700")) { throw new RuntimeException("撞树上了"); } return firstComeBus; }).exceptionally(e -> { SmallTool.printTimeAndThread("小白叫出租车"); SmallTool.sleepMillis(200); return "出租车 叫到了"; }); SmallTool.printTimeAndThread(String.format("%s",future.join())); }
6、allOf:等待所有CompletableFuture执行完毕
@Test public void test8() { System.out.println(Runtime.getRuntime().availableProcessors());//获取计算机可用线程数 //System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "10"); 设置自定义线程最大线程数 //查看当前线程数 System.out.println(ForkJoinPool.commonPool().getPoolSize()); //查看最大线程数 System.out.println(ForkJoinPool.getCommonPoolParallelism()); SmallTool.printTimeAndThread("小白和小伙伴们 进餐厅点餐"); long l = System.currentTimeMillis(); /* ArrayList<Dish> dishes = new ArrayList<>(); //点菜 for(int i = 1; i <= 10; i++) { Dish dish = new Dish("菜" + i, 1); dishes.add(dish); } ArrayList<CompletableFuture> completableFutures = new ArrayList<>(); //做菜 for (Dish dish : dishes) { CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(dish::make); completableFutures.add(completableFuture); } //等待所有异步任务执行完毕 CompletableFuture[] array = completableFutures.toArray(new CompletableFuture[completableFutures.size()]);*/ //Stream方式实现 CompletableFuture[] array = IntStream.rangeClosed(1, 10) //大于当前电脑线程数会超过2秒 .mapToObj(i -> new Dish("菜" + i, 1)) .map(dish -> CompletableFuture.runAsync(dish::makeUseCPU)) .toArray(CompletableFuture[]::new); CompletableFuture<Void> completableFuture = CompletableFuture.allOf(array); completableFuture.join(); SmallTool.printTimeAndThread("菜做好了, 上桌 " + (System.currentTimeMillis() - l)); }
SmallTool工具类
public class SmallTool { public static void sleepMillis(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } public static void printTimeAndThread(String tag) { String s = new StringJoiner("\t|\t") .add(String.valueOf(System.currentTimeMillis())) .add(String.valueOf(Thread.currentThread().getId())) .add(Thread.currentThread().getName()) .add(tag) .toString(); System.out.println(s); } }
Dish类
public class Dish { //菜名 private String name; //制作时长 private Integer productionTime; public Dish(String name, Integer productionTime) { this.name = name; this.productionTime = productionTime; } public void make() { SmallTool.sleepMillis(TimeUnit.SECONDS.toMillis(this.productionTime)); SmallTool.printTimeAndThread(this.name + " 制作完毕,来吃我把"); } public void makeUseCPU() { SmallTool.printTimeAndThread(this.name + " 制作完毕,来吃我把" + compute()); } private static long compute() { //当前电脑计算时间为1秒左右 long l = System.currentTimeMillis(); long result = 0; for(int i = 0; i < Integer.MAX_VALUE / 3; i++) { result += i * i % 3; } return System.currentTimeMillis() - l; } public static void main(String[] args) { System.out.println(compute()); } }
最后 ArrayList转数组的方法
// 创建一个动态数组 ArrayList<String> sites = new ArrayList<>(); sites.add("Runoob"); sites.add("Google"); sites.add("Wiki"); sites.add("Taobao"); //默认转换为Object类型
Object[] objects = sites.toArray();
// 转换成想要的类型
String[] strings = sites.toArray(new String[sites.size()]);
//分开写就是把list写入一个新的arr中
String[] arr = new String[sites.size()];
sites.toArray(arr);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)