当前位置: 首页 > article >正文

Java并发编程:CompletableFuture实战

Java并发编程CompletableFuture实战引言Java 8引入的CompletableFuture是现代异步编程的重要工具它不仅解决了Future的局限性还提供了丰富的API用于组合、转换和处理异步结果。相比传统的FutureCompletableFuture支持流式调用、回调函数和声明式的异常处理大大简化了异步代码的编写。Spring Boot和各类Web框架都广泛使用CompletableFuture来处理异步任务。本文将全面介绍CompletableFuture的使用方法、实战技巧和最佳实践。一、Future的局限性1.1 传统Future的问题JDK 5引入的Future提供了一种获取异步任务结果的方式但它存在明显的局限性无法手动完成当异步任务完成后无法主动通知等待的线程不支持链式调用多个依赖的异步任务无法优雅地串联执行不支持组合操作对多个Future进行合并操作需要复杂的编码异常处理困难Future.get()会将异常封装在ExecutionException中处理起来不够直观。1.2 CompletableFuture的优势CompletableFuture完美解决了这些问题。它支持函数式编程风格可以链式调用thenApply、thenCompose等方法内置丰富的组合操作如thenCombine、allOf、anyOf等支持回调模式无需阻塞等待结果提供完善的异常处理机制通过exceptionally、handle等方法优雅处理异常。二、创建CompletableFuture2.1 基本创建方式public class CompletableFutureCreation { // 1. 使用completedFuture创建已完成的Future public CompletableFutureString createCompleted() { return CompletableFuture.completedFuture(预定义结果); } // 2. 使用supplyAsync创建异步任务 public CompletableFutureString createAsync() { return CompletableFuture.supplyAsync(() - { // 模拟耗时操作 try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return 异步计算结果; }); } // 3. 使用runAsync执行不需要返回值的任务 public CompletableFutureVoid createVoidAsync() { return CompletableFuture.runAsync(() - { System.out.println(执行异步任务线程: Thread.currentThread().getName()); }); } // 4. 指定线程池 public CompletableFutureString createWithExecutor(Executor executor) { return CompletableFuture.supplyAsync(() - { return 使用自定义线程池; }, executor); } }2.2 手动完成Futurepublic class ManualCompletion { public CompletableFutureString processWithTimeout() { CompletableFutureString future new CompletableFuture(); // 模拟异步处理 new Thread(() - { try { String result doProcess(); future.complete(result); } catch (Exception e) { future.completeExceptionally(e); } }).start(); // 设置超时 CompletableFutureString timeoutFuture future .orTimeout(5, TimeUnit.SECONDS) .whenComplete((result, ex) - { if (ex ! null) { System.out.println(处理超时或失败: ex.getMessage()); } else { System.out.println(处理完成: result); } }); return timeoutFuture; } private String doProcess() throws InterruptedException { Thread.sleep(3000); return 处理结果; } }三、转换和消费结果3.1 thenApply系列方法thenApply用于对结果进行转换处理类似Stream的map操作。public class TransformationDemo { public CompletableFutureInteger applyDemo() { return CompletableFuture.supplyAsync(() - 123) .thenApply(Integer::parseInt) // String - Integer .thenApply(n - n * 2) // Integer - Integer .thenApply(n - 结果: n); // 最终转为String } public CompletableFutureString applyWithAsync() { return CompletableFuture.supplyAsync(() - hello) .thenApplyAsync(s - { System.out.println(异步转换线程: Thread.currentThread().getName()); return s.toUpperCase(); }); } // thenApply接收Function支持返回值 // thenAccept接收Consumer只消费不返回 // thenRun接收Runnable不关心结果 public void consumeDemo() { CompletableFuture.supplyAsync(() - data) .thenAccept(result - System.out.println(消费结果: result)) .thenRun(() - System.out.println(任务完成)); } }3.2 thenCompose组合Future当异步任务返回另一个CompletableFuture时使用thenCompose进行扁平化处理。public class CompositionDemo { public CompletableFutureString composeDemo(String orderId) { return getOrderAsync(orderId) .thenCompose(order - getUserAsync(order.getUserId())) .thenApply(user - user.getName() 的订单); } private CompletableFutureOrder getOrderAsync(String orderId) { return CompletableFuture.supplyAsync(() - { // 模拟查询订单 Order order new Order(); order.setId(orderId); order.setUserId(user-001); return order; }); } private CompletableFutureUser getUserAsync(String userId) { return CompletableFuture.supplyAsync(() - { // 模拟查询用户 User user new User(); user.setId(userId); user.setName(张三); return user; }); } }3.3 thenCombine合并Future当需要合并两个独立异步任务的结果时使用thenCombine。public class CombinationDemo { public CompletableFutureString combineDemo() { CompletableFutureString future1 CompletableFuture .supplyAsync(() - Hello); CompletableFutureString future2 CompletableFuture .supplyAsync(() - World); return future1.thenCombine(future2, (s1, s2) - s1 s2); } public CompletableFutureUserOrderInfo getUserOrderInfo(String userId) { CompletableFutureUser userFuture getUserAsync(userId); CompletableFutureListOrder ordersFuture getOrdersAsync(userId); return userFuture.thenCombine(ordersFuture, (user, orders) - new UserOrderInfo(user, orders)); } private CompletableFutureUser getUserAsync(String userId) { return CompletableFuture.supplyAsync(() - { User user new User(); user.setId(userId); user.setName(张三); return user; }); } private CompletableFutureListOrder getOrdersAsync(String userId) { return CompletableFuture.supplyAsync(() - { return Arrays.asList(new Order(), new Order()); }); } }四、异常处理4.1 exceptionly处理异常public class ExceptionHandlingDemo { public CompletableFutureString handleWithExceptionally() { return CompletableFuture.supplyAsync(() - { if (true) throw new RuntimeException(测试异常); return 正常结果; }) .exceptionally(ex - { System.out.println(捕获异常: ex.getMessage()); return 默认值; }); } // 无论是否异常都会执行 public CompletableFutureString handleWithHandle(String input) { return CompletableFuture.supplyAsync(() - { if (error.equals(input)) { throw new RuntimeException(业务异常); } return 成功: input; }) .handle((result, ex) - { if (ex ! null) { System.out.println(发生异常已恢复); return 恢复后的值; } return result; }); } // 只处理异常不影响结果传递 public CompletableFutureString handleWithWhenComplete(String input) { return CompletableFuture.supplyAsync(() - { if (error.equals(input)) { throw new RuntimeException(测试异常); } return 成功: input; }) .whenComplete((result, ex) - { if (ex ! null) { System.out.println(记录异常日志: ex.getMessage()); } else { System.out.println(记录成功日志: result); } }); } }4.2 异常传播和抑制public class ExceptionPropagationDemo { public CompletableFutureString exceptionPropagationDemo() { return CompletableFuture .supplyAsync(() - { throw new BusinessException(初始异常); }) .thenApply(result - result.toUpperCase()) // 不会执行 .thenCompose(result - CompletableFuture .supplyAsync(() - { throw new AnotherException(后续异常); }) ) .exceptionally(ex - { // 这里可以访问所有异常 System.out.println(异常链: ex.getCause()); return 默认值; }); } }五、并行处理5.1 allOf等待所有任务public class ParallelProcessingDemo { public CompletableFutureString processAll(ListString ids) { ListCompletableFutureString futures ids.stream() .map(this::processOne) .collect(Collectors.toList()); return CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ) .thenApply(v - futures.stream() .map(CompletableFuture::join) .collect(Collectors.joining(, ))); } public CompletableFutureListString processAllWithResults( ListString ids) { ListCompletableFutureString futures ids.stream() .map(this::processOne) .collect(Collectors.toList()); return CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ) .thenApply(v - futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); } private CompletableFutureString processOne(String id) { return CompletableFuture.supplyAsync(() - { System.out.println(处理 id 线程: Thread.currentThread().getName()); return 结果- id; }); } }5.2 anyOf获取最先完成的结果public class FirstCompleteDemo { public CompletableFutureObject getFirstAvailable( String... services) { ListCompletableFutureString futures Arrays.stream(services) .map(this::queryService) .collect(Collectors.toList()); CompletableFutureObject anyFuture CompletableFuture .anyOf(futures.toArray(new CompletableFuture[0])); return anyFuture; } private CompletableFutureString queryService(String serviceName) { return CompletableFuture.supplyAsync(() - { // 模拟服务查询不同服务响应时间不同 int delay new Random().nextInt(3000); try { Thread.sleep(delay); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return serviceName -响应- delay ms; }); } }六、实战应用6.1 异步HTTP调用Service public class AsyncHttpService { private final RestTemplate restTemplate; private final ExecutorService executor; public AsyncHttpService(RestTemplate restTemplate) { this.restTemplate restTemplate; this.executor Executors.newFixedThreadPool(10); } public CompletableFutureUser getUser(String userId) { return CompletableFuture.supplyAsync(() - { String url http://user-service/api/users/ userId; return restTemplate.getForObject(url, User.class); }, executor); } public CompletableFutureOrderDetail getOrderWithUser(String orderId) { return getOrderAsync(orderId) .thenCompose(order - getUser(order.getUserId()) .thenApply(user - new OrderDetail(order, user))); } public CompletableFutureListProduct getRecommendedProducts( ListString productIds) { ListCompletableFutureProduct futures productIds.stream() .map(id - CompletableFuture.supplyAsync( () - getProductFromService(id), executor)) .collect(Collectors.toList()); return CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ) .thenApply(v - futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); } private Order getOrderAsync(String orderId) { return restTemplate.getForObject( http://order-service/api/orders/ orderId, Order.class); } private Product getProductFromService(String productId) { return restTemplate.getForObject( http://product-service/api/products/ productId, Product.class); } }6.2 异步数据处理管道Service public class DataProcessingPipeline { public CompletableFutureProcessedData processDataPipeline( RawData raw) { return CompletableFuture .supplyAsync(() - validate(raw)) .thenApply(this::clean) .thenApply(this::transform) .thenApplyAsync(this::enrich) // 异步Enrichment可能较慢 .thenApply(this::aggregate) .exceptionally(ex - { log.error(数据处理失败: {}, ex.getMessage()); return createDefaultResult(raw); }); } private RawData validate(RawData raw) { if (raw null) { throw new IllegalArgumentException(原始数据不能为空); } return raw; } private CleanedData clean(RawData raw) { return new CleanedData(raw.getValue().trim()); } private TransformedData transform(CleanedData cleaned) { return new TransformedData(cleaned.getValue().toUpperCase()); } private EnrichedData enrich(TransformedData transformed) { // 添加额外的 enrichment 数据 return new EnrichedData(transformed); } private ProcessedData aggregate(EnrichedData enriched) { return new ProcessedData(enriched.getValue()); } private ProcessedData createDefaultResult(RawData raw) { return new ProcessedData(默认值); } }6.3 超时控制和重试public class TimeoutAndRetryDemo { public CompletableFutureString withTimeout( CompletableFutureString future, long timeoutSeconds) { return future.orTimeout(timeoutSeconds, TimeUnit.SECONDS) .exceptionally(ex - { System.out.println(任务超时: ex.getMessage()); return 超时默认值; }); } public CompletableFutureString withRetry( SupplierString operation, int maxRetries) { return CompletableFuture.supplyAsync(operation) .exceptionallyCompose(ex - { if (maxRetries 0) { System.out.println(重试中剩余次数: (maxRetries - 1)); return withRetry(operation, maxRetries - 1); } throw new CompletionException(ex); }); } public CompletableFutureString retryWithBackoff( SupplierString operation, int maxRetries) { return CompletableFuture.supplyAsync(operation) .exceptionallyCompose(ex - { if (maxRetries 0) { long delay (long) Math.pow(2, 5 - maxRetries) * 1000; System.out.println(等待 delay ms 后重试...); return CompletableFuture .delayedFuture(delay, TimeUnit.MILLISECONDS) .thenCompose(v - retryWithBackoff(operation, maxRetries - 1)); } throw new CompletionException(ex); }); } }七、性能优化建议7.1 使用自定义线程池默认的ForkJoinPool.commonPool()适合计算密集型任务但对于IO密集型任务建议使用自定义线程池以获得更好的性能。Configuration public class CompletableFutureConfig { Bean(completableFutureExecutor) public ExecutorService completableFutureExecutor() { return new ThreadPoolExecutor( 20, // corePoolSize 100, // maxPoolSize 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(500), new ThreadFactoryBuilder() .setNameFormat(cf-pool-%d) .build(), new ThreadPoolExecutor.CallerRunsPolicy() ); } }7.2 避免过度嵌套使用thenCompose扁平化嵌套的CompletableFuture避免回调地狱。7.3 合理使用同步方法thenApply等方法的Async版本会创建新任务开销如果操作很快完成使用同步版本更高效。总结CompletableFuture是Java异步编程的核心工具它提供了丰富的API来支持各种异步场景。通过supplyAsync、thenApply、thenCompose、thenCombine等方法可以优雅地处理异步任务的创建、转换、组合和异常。掌握CompletableFuture的使用对于构建高性能的Java应用至关重要。在实际开发中需要根据业务场景合理设计异步流程并注意线程池配置和异常处理才能真正发挥异步编程的优势。

相关文章:

Java并发编程:CompletableFuture实战

Java并发编程:CompletableFuture实战 引言 Java 8引入的CompletableFuture是现代异步编程的重要工具,它不仅解决了Future的局限性,还提供了丰富的API用于组合、转换和处理异步结果。相比传统的Future,CompletableFuture支持流式调…...

极简风项目交付倒计时!:紧急修复MJ --v 6.2中隐藏的1.33倍宽高比偏移Bug,避免客户验收驳回(含补救Prompt包)

更多请点击: https://intelliparadigm.com 第一章:极简风项目交付倒计时! 当交付周期压缩至 72 小时,极简风不再是一种美学选择,而是工程效率的刚性约束。我们摒弃冗余文档、跳过非核心评审环节,聚焦于可…...

AI智能体任务编排框架:从概念到实战的Mission Control指南

1. 项目概述:为AI智能体打造一个“任务控制中心”最近在折腾AI智能体(Agent)的开发,发现一个挺普遍的问题:当你想让多个智能体协同工作,或者想让单个智能体执行一系列复杂、有依赖关系的任务时,…...

一键获取Steam游戏清单:Onekey工具让游戏管理变得如此简单

一键获取Steam游戏清单:Onekey工具让游戏管理变得如此简单 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 你是否曾为管理Steam游戏文件而烦恼?想备份心爱的游戏却不知从…...

城通网盘解析工具:3步获取高速直连下载地址的终极方案

城通网盘解析工具:3步获取高速直连下载地址的终极方案 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 你是否还在为城通网盘的蜗牛下载速度而烦恼?每次下载大文件都要经历漫长的…...

DaVinci Developer与Configurator Pro联调指南:如何高效设计SWC并集成到ECU工程

DaVinci Developer与Configurator Pro联调实战:从SWC设计到ECU集成的全流程解析 在汽车电子控制单元(ECU)开发领域,工具链的协同效率直接决定了项目进度和质量。作为Vector公司AUTOSAR工具链的核心组件,DaVinci Develo…...

网盘下载新革命:九大平台一键直链,告别客户端束缚

网盘下载新革命:九大平台一键直链,告别客户端束缚 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘…...

ComfyUI Video Combine节点3个核心技巧:解决视频合并常见问题

ComfyUI Video Combine节点3个核心技巧:解决视频合并常见问题 【免费下载链接】ComfyUI-VideoHelperSuite Nodes related to video workflows 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-VideoHelperSuite 在AI动画创作中,ComfyUI的Vi…...

解锁端侧智能:基于BigDL-LLM与Qwen-1.8B-Chat的CPU高效推理实践

1. 为什么要在CPU上部署大模型? 最近两年大模型技术发展迅猛,但大多数应用都依赖昂贵的GPU服务器。我在实际项目中发现,很多中小企业和个人开发者其实更需要能在普通电脑上运行的轻量化方案。这就是为什么基于CPU的大模型部署方案变得越来越…...

AI驱动博客平台CodeBlog-app:开发者技术分享的智能解决方案

1. 项目概述:一个为开发者而生的AI驱动博客平台最近在GitHub上看到一个挺有意思的开源项目,叫CodeBlog-ai/codeblog-app。光看名字,你可能会觉得这又是一个普通的博客系统,或者是一个AI写作工具。但当我深入去研究它的代码和设计理…...

GD32F103C8T6烧录方式全解析:串口ISP、ST-Link Utility、Keil在线,哪种最适合你?

GD32F103C8T6烧录方案深度评测:从原型开发到量产部署的全场景指南 在嵌入式开发领域,选择正确的程序烧录方式往往决定着开发效率和生产成本。作为STM32F103的国产替代方案,GD32F103C8T6凭借其出色的性价比赢得了广泛关注。但许多开发者在迁移…...

无线渗透测试框架Airecon:自动化工具链整合与实战应用

1. 项目概述与核心价值最近在整理自己的渗透测试工具箱时,又翻出了pikpikcu/airecon这个老伙计。说实话,在无线安全评估这个细分领域里,它可能不是名气最响的那个,但绝对是我个人在内部网络渗透和红队演练中最顺手、最高效的“组合…...

2026年主流抓娃娃App大对比,哪个才是你的“抓宝神器”?

在当今快节奏的生活中,年轻人面临着来自学业、工作、社交等多方面的压力。为了缓解这些压力,寻找适合的解压方式成为了大家的共同需求。抓娃娃App作为一种新兴的娱乐方式,正逐渐受到年轻人的喜爱。下面我们就从潮流趋势、科技前沿、行业洞察等…...

告别内置ADC的烦恼:用ADS1119搞定STM32/DSP的高精度电压采样(附完整代码)

告别内置ADC的烦恼:用ADS1119搞定STM32/DSP的高精度电压采样(附完整代码) 在嵌入式系统开发中,电压采样是基础却至关重要的环节。许多工程师在使用STM32或DSP内置ADC时,常会遇到精度不足、抗干扰能力差、无法测量差分信…...

保姆级教程:在Ubuntu 20.04上从源码编译aarch64-linux-gnu交叉工具链(GCC 9.2.0 + Glibc 2.30)

深度实践:从源码构建aarch64-linux-gnu交叉工具链全指南 在嵌入式开发领域,交叉编译工具链的构建能力是区分普通开发者与资深工程师的重要标志。当现成的预编译工具链无法满足特定需求时,从源码手动构建工具链不仅能解决兼容性问题&#xff0…...

从PUMA560到你的项目:手把手教你将经典DH建模流程迁移到自定义机械臂

从PUMA560到自定义机械臂:DH建模实战迁移指南 当机械臂从教科书案例走向真实项目时,最令人头疼的莫过于面对一个全新构型却不知如何下手。本文将以工业界经典的PUMA560为跳板,拆解一套可迁移的DH建模方法论,带您跨越从理论到实践的…...

LLM Notebooks:从零构建RAG问答系统的实践指南

1. 项目概述:一个面向大语言模型实践的“笔记本”仓库最近在GitHub上闲逛,发现了一个挺有意思的仓库,叫qianniuspace/llm_notebooks。光看名字,llm_notebooks,大语言模型笔记本,这指向性就非常明确了。这大…...

STM32CubeMX外设配置实战——以F103C8T6的CAN与DMA为例

1. STM32CubeMX与F103C8T6开发基础 STM32CubeMX是ST官方推出的图形化配置工具,它能极大简化STM32系列MCU的外设初始化流程。对于刚接触STM32开发的工程师来说,这个工具就像"乐高积木说明书"——通过可视化操作就能完成80%的底层配置工作。我最…...

SOCD Cleaner终极指南:彻底解决游戏键盘方向冲突的免费开源神器

SOCD Cleaner终极指南:彻底解决游戏键盘方向冲突的免费开源神器 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 还在为格斗游戏中同时按下W和S导致角色卡顿而烦恼吗?或者在射击游戏急停转…...

AI量化交易框架解析:从架构设计到实战部署

1. 项目概述:一个AI驱动的加密资产对冲基金框架最近在GitHub上看到一个挺有意思的项目,叫“ai-hedge-fund-crypto”。光看名字,就能感受到一股浓浓的“量化AI加密”的混合气息。这其实是一个开源框架,旨在帮助开发者或量化研究员&…...

Fast-GitHub:打破GitHub访问壁垒的智能加速方案

Fast-GitHub:打破GitHub访问壁垒的智能加速方案 【免费下载链接】Fast-GitHub 国内Github下载很慢,用上了这个插件后,下载速度嗖嗖嗖的~! 项目地址: https://gitcode.com/gh_mirrors/fa/Fast-GitHub 你是否曾因GitHub仓库克…...

HS2-HF_Patch终极指南:一键为Honey Select 2安装完整增强补丁

HS2-HF_Patch终极指南:一键为Honey Select 2安装完整增强补丁 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch HS2-HF_Patch是专为《Honey Select 2》…...

如何安全备份微信聊天记录:PyWxDump工具使用全指南

如何安全备份微信聊天记录:PyWxDump工具使用全指南 【免费下载链接】PyWxDump 删库 项目地址: https://gitcode.com/GitHub_Trending/py/PyWxDump 你是否曾因误删重要微信对话而懊悔不已?是否想永久保存珍贵聊天记录却不知从何下手?Py…...

对比直接使用厂商 API 体验 Taotoken 在路由容灾上的价值

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比直接使用厂商 API 体验 Taotoken 在路由容灾上的价值 在开发依赖大模型能力的应用时,服务的连续性与稳定性是保障用…...

从零构建AOD-Net:PyTorch实战图像去雾模型开发全流程

1. 环境准备与数据理解 在开始构建AOD-Net之前,我们需要先搭建好开发环境。推荐使用Anaconda创建独立的Python环境,避免与其他项目产生依赖冲突。这里我选择Python 3.8和PyTorch 1.12的组合,这个版本经过实测在图像处理任务中表现稳定。 安装…...

用Python复现FAST天眼数学建模:从坐标变换到促动器伸缩量计算(附完整代码)

用Python复现FAST天眼数学建模:从坐标变换到促动器伸缩量计算(附完整代码) 中国天眼FAST作为全球最大单口径射电望远镜,其主动反射面调节系统堪称现代工程奇迹。当观测不同方位天体时,需要通过促动器精确控制4450块反射…...

5秒无损转换B站缓存视频:m4s-converter完整使用指南

5秒无损转换B站缓存视频:m4s-converter完整使用指南 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经在B站缓存了珍贵的学习…...

终极macOS清理神器:Pearcleaner 3步彻底卸载应用不留痕迹

终极macOS清理神器:Pearcleaner 3步彻底卸载应用不留痕迹 【免费下载链接】Pearcleaner A free, source-available and fair-code licensed mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner 你是否曾将macOS应用拖入废纸篓后&…...

用ZYNQ和LWIP搞定8路ADS8681数据采集:从Vivado Block Design到上位机TCP通信的完整流程

ZYNQ与LWIP构建的8通道高速数据采集系统实战指南 在工业自动化、测试测量和科研领域,多通道高精度数据采集系统正变得越来越重要。本文将详细介绍如何利用Xilinx ZYNQ SoC和LWIP协议栈,构建一个支持8路ADS8681同步采集的实时数据传输系统。不同于简单的代…...

从8K游戏到HDR电影:拆解Xilinx HDMI 2.1 IP如何支持VRR、ALLM和动态HDR这些炫酷特性

从8K游戏到HDR电影:Xilinx HDMI 2.1 IP如何重塑视听体验 当PS5玩家在《战神:诸神黄昏》中感受到无撕裂的流畅战斗画面,或是家庭影院爱好者在《沙丘》中看到沙漠场景的每一粒沙粒都呈现出惊人的动态范围时,背后都离不开HDMI 2.1的关…...