首页 > 其他分享 >CompletableFuture优雅处理并发最佳实践

CompletableFuture优雅处理并发最佳实践

时间:2024-09-26 11:14:04浏览次数:10  
标签:task return simulateTask 优雅 并发 future CompletableFuture supplyAsync

1、 supplyAsync方法需要一个Supplier函数接口,通常用于执行异步计算

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    dosomething("处理事务");
    return "结果";
});

2、 runAsync接受一个Runnable函数接口,不关心异步任务的结果

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    dosomething("处理事务");
});

3、 组合使用

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    simulateTask("task-1");
    return "task-1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    simulateTask("task-2");
    return "task-2";
});

// 组合两个future,等待它们都完成
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (task-1, task-2) -> {
    return "==== " + task-1+ "," + task-2;
});

4、链式调用

  • thenApply用于处理和转换CompletableFuture的结果
  • thenAccept用于消费CompletableFuture的结果,不返回新的CompletableFuture
  • thenRun则不关心前一个任务的结果,只是在前一个任务执行完后,执行一些后续操作
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    simulateTask("task-1");
    return "task-1";
});
future.thenApply(result -> {
    return "处理后的结果:" + result;
}).thenAccept(processedResult -> {
    System.out.println("最终结果:" + processedResult);
}).thenRun(() -> {
    System.out.println("所有操作完成");
});

5、 基本异常处理

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (new Random().nextBoolean()) {
        throw new RuntimeException("出错啦!");
    }
    return "正常结果";
}).exceptionally(ex -> {
    return "错误:" + ex.getMessage();
});

future.thenAccept(System.out::println);

6、异常继续处理

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (new Random().nextBoolean()) {
        throw new RuntimeException("出错啦!");
    }
    return "正常结果";
}).handle((result, ex) -> {
    if (ex != null) {
        return "处理异常:" + ex.getMessage();
    }
    return "处理结果:" + result;
});
future.thenAccept(System.out::println);

7、 依赖关系

CompletableFuture<String> masterFuture = CompletableFuture.supplyAsync(() -> {
    simulateTask("task-1");
    return "task-1";
});

CompletableFuture<String> dependentFuture = masterFuture.thenCompose(result -> {
    return CompletableFuture.supplyAsync(() -> {
        simulateTask("处理依赖于" + result + "的数据");
        return "处理后的数据";
    });
});

dependentFuture.thenAccept(System.out::println);

8、 处理多个Future

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    simulateTask("任务一");
    return "结果一";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    simulateTask("任务二");
    return "结果二";
});

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);

allFutures.thenRun(() -> {
    System.out.println("所有任务完成");
});

CompletableFuture默认情况下使用ForkJoinPool,但在某些场景下使用自定义线程池可更好地控制资源

ExecutorService customExecutor = Executors.newFixedThreadPool(10);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    return "使用自定义线程池";
}, customExecutor);

当组合多个CompletableFuture,对每一个Future都进行错误处理,避免一个未捕获的异常破坏整个操作链

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "任务1").exceptionally(ex -> "默认值1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "任务2").exceptionally(ex -> "默认值2");
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " 和 " + result2);

标签:task,return,simulateTask,优雅,并发,future,CompletableFuture,supplyAsync
From: https://www.cnblogs.com/codechange/p/18433064

相关文章

  • Linux单机最大并发到底是多少?
    Linux单机最大并发到底是多少?-知乎(zhihu.com)所谓C10K就是单机1w并发问题,其中IO复用epoll/kqueue/iocp等技术对于C10k问题的解决起到了非常重要的作用。所谓C10W就是单机1000w并发问题,未来待解决==========================================五元组数一个五元组可以唯一标......
  • nginx: 限制每个ip的并发连接数
    一,limit_conn_zonelimit_conn_zone$binary_remote_addrzone=perip:10m; limit_conn模块用于限制每个客户端的并发连接数,以防止资源被单一客户端耗尽。说明: #定义一个共享内存区域,用于存储连接状态#$binary_remote_addr是客户端的IP地址#zone=perip:10m定义名为......
  • 精通Java并发锁机制:24种锁技巧+业务锁匹配方案(第一部分)
    在Java并发编程中,锁是确保线程安全、协调多线程访问共享资源的关键机制。从基本的synchronized同步关键字到高级的ReentrantLock、读写锁ReadWriteLock、无锁设计如AtomicInteger,再到复杂的同步辅助工具如CountDownLatch、CyclicBarrier和Semaphore,每种锁都针对......
  • 精通Java并发锁机制:24种锁技巧+业务锁匹配方案(第一部分)
    在Java并发编程中,锁是确保线程安全、协调多线程访问共享资源的关键机制。从基本的synchronized同步关键字到高级的ReentrantLock、读写锁ReadWriteLock、无锁设计如AtomicInteger,再到复杂的同步辅助工具如CountDownLatch、CyclicBarrier和Semaphore,每种锁都针对特定的......
  • 并发处理的利器:深入探讨锁分离设计+6大分离场景(高并发篇)
    锁分离设计的本质在于将对共享资源的访问操作根据其类型或性质区分开来,并为每种操作提供独立的锁。这种设计背景通常源于对高并发系统的需求,其中多个线程或进程需要频繁地对共享资源进行读写或其他操作。在传统的锁机制中,所有操作都可能使用同一把锁,这在高并发环境下会导致......
  • 【c++实战项目】从零实现一个高并发内存池
    主页:醋溜马桶圈-CSDN博客专栏:实战项目_醋溜马桶圈的博客-CSDN博客gitee:mnxcc(mnxcc)-Gitee.com目录1.项目介绍1.1 这个项目做的是什么?1.2这个项目的要求的知识储备和难度?2.什么是内存池2.1 池化技术2.2 内存池2.3 内存池主要解决的问题2.4malloc3.开胃......
  • C# + WPF 音频播放器 界面优雅,体验良好
    C#+WPF音频播放器界面优雅,体验良好 合集-.NET开源工具(18)  阅读目录前言项目介绍项目页面项目源码项目地址最后前言本文介绍一款使用C#与WPF开发的音频播放器,其界面简洁大方,操作体验流畅。该播放器支持多种音频格式(如MP4、WMA、OGG、FLAC......
  • 【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
    文章目录C++`vector`容器详解:从入门到精通前言第一章:C++`vector`容器简介1.1C++STL容器概述1.2为什么使用`vector`1.3`vector`的优缺点第二章:`vector`的构造方法2.1常见构造函数2.1.1示例:不同构造方法2.1.2相关文档第三章:`vector`容量与大小操作3.1......
  • 【JUC并发编程系列】深入理解Java并发机制:阻塞队列详解与简单纯手写(七、BlockingQueu
    文章目录【JUC并发编程系列】深入理解Java并发机制:阻塞队列详解与简单纯手写(七、BlockingQueue、ArrayBlockingQueue、LinkedBlocking)1.简单回顾1.1数组结构和链表结构1.1.1数组结构1.1.2链表结构1.2有界队列与无界队列1.3Lock锁使用回顾2.什么是阻塞队列3.B......
  • 【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、
    文章目录【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、Volatile关键字、JMM、重排序、双重检验锁)1.Volatile的特性2.Volatile的用法3.CPU多核硬件架构剖析4.JMM内存模型4.1主要特性4.2JMM的工作原理4.3实现机制5.JMM八......