【多线程编程】CompletableFuture 使用指南(基础篇):从原理到 API

文章目录

    • 一、为什么需要 CompletableFuture(Why CompletableFuture):解决异步编程的核心痛点
      • 1.1 传统 Future 的困境:串行慢、并行复杂
      • 1.2 CompletableFuture 的解决方案:简单、高效、可靠
    • 二、CompletableFuture 的实现原理(Implementation Principles):理解其设计思想
      • 2.1 核心数据结构:状态机 + 回调链表(实现无锁异步编排的基础)
      • 2.2 CAS 无锁机制:保证线程安全的高性能方案(避免锁竞争,提升并发性能)
      • 2.3 回调链机制:实现任务组合的核心(延迟执行,链式传播)
      • 2.4 线程池复用:默认使用公共线程池(合理配置线程池,避免资源浪费)
    • 三、核心 API 详解(Core APIs):从基础到高级
      • 3.1 创建异步任务:supplyAsync vs runAsync
      • 3.2 转换操作:thenApply vs thenCompose
      • 3.3 组合操作:thenCombine vs allOf
      • 3.4 异常处理:exceptionally vs handle

想象一下这样的场景:你需要查询用户信息、订单列表和积分数据,传统方式是一个接一个地等待,总耗时 650 毫秒。而使用 CompletableFuture,这三个查询可以同时进行,总耗时只需要 300 毫秒——这就是异步编程带来的性能飞跃。

就像餐厅里,传统方式是一个服务员按顺序服务每桌客人,而 CompletableFuture 让多个服务员同时工作,最后统一汇总结果。这种"并行执行、统一汇总"的设计,让 Java 并发编程从"复杂的手动管理"变成了"简单的链式组合"。

核心要点

  1. 非阻塞执行:任务在后台线程执行,主线程不被阻塞,可以继续处理其他逻辑
  2. 灵活组合:可以轻松组合多个异步任务,实现复杂的业务逻辑链
  3. 异常传播:完善的异常处理机制,让异步编程的错误处理变得简单可靠
  4. 性能提升:通过并行执行,将串行耗时变为并行耗时,性能提升可达数倍

一、为什么需要 CompletableFuture(Why CompletableFuture):解决异步编程的核心痛点

核心结论:CompletableFuture 解决了传统 Future 的阻塞等待、组合困难、异常处理复杂三大痛点,让异步编程从"技术实现"变成了"业务表达"。

1.1 传统 Future 的困境:串行慢、并行复杂

很多人都有这样的困扰:当我们需要并行执行多个任务时,传统的方式要么是串行等待(慢),要么是手动管理线程(复杂)。

以查询用户信息为例,传统方式可能是这样:

// 串行方式:总耗时 = 查询用户 + 查询订单 + 查询积分UserInfouser=userService.getUserInfo(userId);// 耗时 200msList<Order>orders=orderService.getOrders(userId);// 耗时 300msPointsInfopoints=pointsService.getPoints(userId);// 耗时 150ms// 总耗时:650ms

如果用 Future,虽然可以并行,但代码复杂:

ExecutorServiceexecutor=Executors.newFixedThreadPool(3);Future<UserInfo>userFuture=executor.submit(()->userService.getUserInfo(userId));Future<List<Order>>ordersFuture=executor.submit(()->orderService.getOrders(userId));Future<PointsInfo>pointsFuture=executor.submit(()->pointsService.getPoints(userId));// 需要手动等待和获取结果UserInfouser=userFuture.get();// 阻塞等待List<Order>orders=ordersFuture.get();// 阻塞等待PointsInfopoints=pointsFuture.get();// 阻塞等待// 总耗时:300ms(最慢的那个),但代码复杂,异常处理困难

1.2 CompletableFuture 的解决方案:简单、高效、可靠

CompletableFuture 让这一切变得简单:

CompletableFuture<UserInfo>userFuture=CompletableFuture.supplyAsync(()->userService.getUserInfo(userId));CompletableFuture<List<Order>>ordersFuture=CompletableFuture.supplyAsync(()->orderService.getOrders(userId));CompletableFuture<PointsInfo>pointsFuture=CompletableFuture.supplyAsync(()->pointsService.getPoints(userId));// 等待所有完成并组合结果CompletableFuture.allOf(userFuture,ordersFuture,pointsFuture).join();// 总耗时:300ms,代码简洁,异常处理完善

allOf(...).join()方法详解

CompletableFuture.allOf(...).join()是等待多个并行任务完成的常用模式,由两部分组成:

任务执行时机

任务在supplyAsync()调用时立即提交到线程池并开始执行,而不是在allOf()join()时才开始:

// 第1行:立即提交到线程池,任务开始执行(异步)CompletableFuture<UserInfo>userFuture=CompletableFuture.supplyAsync(()->userService.getUserInfo(userId)// ← 此时任务已经在后台线程执行);// 第2行:立即提交到线程池,任务开始执行(异步)CompletableFuture<List<Order>>ordersFuture=CompletableFuture.supplyAsync(()->orderService.getOrders(userId)// ← 此时任务已经在后台线程执行);// 第3行:立即提交到线程池,任务开始执行(异步)CompletableFuture<PointsInfo>pointsFuture=CompletableFuture.supplyAsync(()->pointsService.getPoints(userId)// ← 此时任务已经在后台线程执行);// 第4行:只是等待所有任务完成,不触发执行(任务已经在执行中)CompletableFuture.allOf(userFuture,ordersFuture,pointsFuture).join();// ↑ 此时三个任务可能已经完成,也可能还在执行中

关键理解

  • supplyAsync():立即提交任务到线程池,任务开始异步执行
  • allOf():只等待完成,不触发执行(任务已经在执行)
  • join():阻塞等待,不触发执行(任务已经在执行)
  1. allOf(...)

    • 静态方法,接收多个CompletableFuture作为参数
    • 返回一个新的CompletableFuture<Void>,当所有传入的任务都完成时(无论成功还是失败),这个新的 Future 才会完成
    • 不关心各个任务的具体返回值,只关心是否全部完成
    • 不触发任务执行:任务在supplyAsync()时已经执行
  2. .join()

    • 阻塞当前线程,直到所有任务完成
    • 如果所有任务成功完成,返回null(因为allOf返回CompletableFuture<Void>
    • 如果任何一个任务失败,会抛出CompletionException,包装原始异常
    • 不触发任务执行:只是等待,任务已经在执行中

执行流程示例

时间线: 0ms → 启动3个异步任务(并行执行) ├─ userFuture (100ms) ├─ ordersFuture (200ms) └─ pointsFuture (300ms) 100ms → userFuture 完成 ✓ 200ms → ordersFuture 完成 ✓ 300ms → pointsFuture 完成 ✓ → allOf().join() 返回(所有任务完成)

关键特性

  • 并行执行:三个任务同时启动,并行执行,而不是串行等待
  • 阻塞等待join()会阻塞当前线程,直到最慢的任务完成(300ms)
  • 异常处理:如果任何一个任务失败,join()会抛出异常,需要 try-catch 处理

获取结果

// allOf().join() 只等待完成,不返回结果// 需要单独调用各 future 的 join() 获取结果allOf(userFuture,ordersFuture,pointsFuture).join();UserInfouser=userFuture.join();// 立即返回(已完成)List<Order>orders=ordersFuture.join();// 立即返回(已完成)PointsInfopoints=pointsFuture.join();// 立即返回(已完成)

二、CompletableFuture 的实现原理(Implementation Principles):理解其设计思想

核心结论:CompletableFuture 通过 CAS(Compare-And-Swap)操作和栈式回调链表实现无锁的异步任务编排,这是其高性能和灵活性的基础。理解这个原理,就能明白为什么 CompletableFuture 既能保证线程安全,又能实现高效的任务组合。

2.1 核心数据结构:状态机 + 回调链表(实现无锁异步编排的基础)

CompletableFuture 的核心是一个状态机,通过volatile变量和 CAS 操作保证线程安全:

// 核心字段volatileObjectresult;// 存储结果或异常volatileCompletionstack;// 回调链表的栈顶

设计思路

  • result 字段:存储任务结果,如果任务未完成则为 null,完成时存储结果或异常
  • stack 字段:存储所有等待此任务完成的后续操作(回调),形成一个链表栈

2.2 CAS 无锁机制:保证线程安全的高性能方案(避免锁竞争,提升并发性能)

核心结论:CompletableFuture 使用 CAS 操作来更新状态,避免了传统锁的开销,这是其高性能的关键。

// 伪代码:完成任务的逻辑booleancomplete(Tvalue){// 使用 CAS 原子性地设置结果if(CAS(result,null,value)){// 成功设置结果,触发回调链postComplete();returntrue;}returnfalse;// 已经被其他线程完成}

设计优势

  • 无锁设计:避免了锁竞争,提高了并发性能
  • 原子操作:CAS 保证状态更新的原子性,线程安全
  • 高性能:无锁设计让 CompletableFuture 在高并发场景下表现优异

2.3 回调链机制:实现任务组合的核心(延迟执行,链式传播)

核心结论:当任务完成时,会触发回调链的执行,这是实现任务组合的核心机制。

当任务完成时,会触发回调链的执行:

// 伪代码:触发回调链voidpostComplete(){Completionh=stack;// 获取回调链栈顶while(h!=null){Completionnext=h.next;h.tryFire();// 执行回调h=next;}}

设计优势

  • 延迟执行:回调不会立即执行,而是等到任务完成时才执行
  • 链式传播:一个任务的完成会触发后续任务的执行,形成链式反应
  • 线程安全:通过 CAS 操作保证回调链的线程安全

2.4 线程池复用:默认使用公共线程池(合理配置线程池,避免资源浪费)

核心结论:CompletableFuture 默认使用ForkJoinPool.commonPool(),这是一个共享的线程池,合理配置线程池可以避免资源浪费。

CompletableFuture 默认使用ForkJoinPool.commonPool(),这是一个共享的线程池:

// 默认使用公共线程池publicstatic<U>CompletableFuture<U>supplyAsync(Supplier<U>supplier){returnasyncSupplyStage(ASYNC_POOL,supplier);}// 也可以指定自定义线程池publicstatic<U>CompletableFuture<U>supplyAsync(Supplier<U>supplier,Executorexecutor){returnasyncSupplyStage(screenExecutor(executor),supplier);}

最佳实践

  • CPU 密集型任务:使用ForkJoinPool,线程数 = CPU 核心数
  • IO 密集型任务:使用自定义线程池,线程数可以更大(如 50-100)
  • 避免线程泄漏:长时间运行的任务建议使用自定义线程池,便于管理

三、核心 API 详解(Core APIs):从基础到高级

核心结论:CompletableFuture 的 API 分为创建、转换、组合、等待四大类,理解每类的使用场景和原理,才能灵活运用。掌握了这四类 API,就能解决 90% 的并发编程问题。

3.1 创建异步任务:supplyAsync vs runAsync

核心结论:根据任务是否有返回值,选择supplyAsyncrunAsync

// 有返回值的任务CompletableFuture<String>future1=CompletableFuture.supplyAsync(()->{return"结果";});// 无返回值的任务CompletableFuture<Void>future2=CompletableFuture.runAsync(()->{System.out.println("执行完成");});// 已完成的任务(用于测试或组合)CompletableFuture<String>future3=CompletableFuture.completedFuture("已完成");

适用场景

  • supplyAsync:需要返回结果的异步操作(如查询数据库、调用 API)
  • runAsync:只需要执行操作,不需要结果(如发送日志、清理缓存)
  • completedFuture:测试场景,或者需要统一接口的已完成任务

3.2 转换操作:thenApply vs thenCompose

核心结论thenApply是同步转换,在当前线程执行;thenCompose是异步转换,返回新的 CompletableFuture 在后台线程执行。

// thenApply:同步转换,在当前线程执行CompletableFuture<String>future1=CompletableFuture.supplyAsync(()->"Hello").thenApply(s->s+" World");// 同步转换// thenCompose:异步转换,返回新的 CompletableFutureCompletableFuture<String>future2=CompletableFuture.supplyAsync(()->"Hello").thenCompose(s->CompletableFuture.supplyAsync(()->s+" World"));// 异步转换

执行时机和线程

thenApply

  • 执行时机:在前一个任务完成后,立即在当前线程(完成任务的线程)执行
  • 返回值:直接返回转换后的结果(CompletableFuture<U>
  • 线程模型:同步执行,不创建新线程

thenCompose

  • 执行时机:在前一个任务完成后,提交新的异步任务到线程池执行
  • 返回值:返回一个新的CompletableFuture<U>,这个 Future 代表新任务的执行
  • 线程模型:异步执行,创建新线程

实际应用场景对比

场景1:轻量级转换(使用thenApply

// 字符串拼接、数据格式化等轻量级操作CompletableFuture<String>userInfo=CompletableFuture.supplyAsync(()->userService.getUser(userId)).thenApply(user->user.getName()+" ("+user.getEmail()+")");// 总耗时:查询用户时间(转换几乎不耗时)

场景2:重量级操作(使用thenCompose

// 数据库查询、网络请求等重量级操作CompletableFuture<String>userProfile=CompletableFuture.supplyAsync(()->userService.getUser(userId))// 100ms.thenCompose(user->CompletableFuture.supplyAsync(()->orderService.getOrders(user.getId())// 200ms,异步执行));// 总耗时:100ms + 200ms = 300ms(如果串行执行)// 但如果两个任务可以并行,应该用 allOf 而不是 thenCompose

选择原则

  • 轻量级操作(如字符串拼接、简单计算、数据格式化):使用thenApply
    • 优点:不创建新线程,开销小
    • 缺点:会阻塞完成任务的线程
  • 重量级操作(如数据库查询、网络请求、文件IO):使用thenCompose
    • 优点:不阻塞线程,可以充分利用线程池
    • 缺点:创建新线程,有额外开销

为什么重量级操作不能用thenApply

这是一个常见误区。技术上thenApply可以用于重量级操作,但会有严重问题:

// ❌ 问题示例:使用 thenApply 执行重量级操作CompletableFuture<String>future=CompletableFuture.supplyAsync(()->"Hello")// 任务1:快速完成.thenApply(s->{// 问题:这个数据库查询会在哪个线程执行?returndatabaseService.query(s);// 重量级操作,耗时 200ms});

thenApply的执行线程问题

  1. 如果前一个任务已完成

    CompletableFuture<String>f1=CompletableFuture.supplyAsync(()->"Hello");f1.join();// 等待完成// 此时 thenApply 会在调用它的线程中执行(可能是主线程)CompletableFuture<String>f2=f1.thenApply(s->{// 在主线程中执行!会阻塞主线程returndatabaseService.query(s);// 阻塞主线程 200ms});
  2. 如果前一个任务未完成

    CompletableFuture<String>f1=CompletableFuture.supplyAsync(()->{Thread.sleep(100);return"Hello";});// thenApply 会在任务1完成的线程中执行CompletableFuture<String>f2=f1.thenApply(s->{// 在任务1的线程中执行,会阻塞这个线程returndatabaseService.query(s);// 阻塞线程池线程 200ms});

核心问题

  • 阻塞线程thenApply会阻塞执行它的线程(无论是主线程还是线程池线程)
  • 线程资源浪费:线程被阻塞,无法处理其他任务
  • 性能下降:如果线程池线程被阻塞,其他任务可能无法及时执行

正确的做法(使用thenCompose

// ✅ 正确:使用 thenCompose 异步执行重量级操作CompletableFuture<String>future=CompletableFuture.supplyAsync(()->"Hello").thenCompose(s->{// 提交新的异步任务,不阻塞当前线程returnCompletableFuture.supplyAsync(()->databaseService.query(s)// 在新线程中执行,不阻塞);});

性能对比

// 场景:100个并发请求,每个需要查询数据库// ❌ 使用 thenApply(阻塞线程)// 如果线程池有10个线程,每个线程被阻塞200ms// 100个请求需要:100 / 10 * 200ms = 2000ms// ✅ 使用 thenCompose(不阻塞线程)// 线程池线程可以快速处理请求,只负责提交任务// 100个请求可以并行执行,总耗时约 200ms(最慢的那个)

总结

  • thenApply可以用于重量级操作,但会阻塞线程,导致性能问题
  • thenCompose是更好的选择,因为它不阻塞线程,可以充分利用线程池
  • 选择原则:如果操作耗时超过几毫秒,就应该用thenCompose异步执行

注意事项

  • thenApply返回CompletableFuture<U>,但转换是同步的
  • thenCompose返回CompletableFuture<U>,转换是异步的
  • 如果多个任务可以并行执行,应该用allOf而不是thenComposethenCompose是串行的)

3.3 组合操作:thenCombine vs allOf

核心结论thenCombine组合两个任务的结果,allOf等待所有任务完成。

// thenCombine:组合两个任务的结果CompletableFuture<String>future1=CompletableFuture.supplyAsync(()->"Hello");CompletableFuture<String>future2=CompletableFuture.supplyAsync(()->"World");CompletableFuture<String>combined=future1.thenCombine(future2,(s1,s2)->s1+" "+s2);// allOf:等待所有任务完成CompletableFuture<String>f1=CompletableFuture.supplyAsync(()->"Task1");CompletableFuture<String>f2=CompletableFuture.supplyAsync(()->"Task2");CompletableFuture<String>f3=CompletableFuture.supplyAsync(()->"Task3");CompletableFuture.allOf(f1,f2,f3).thenRun(()->{// 所有任务完成后的处理});

使用场景

  • thenCombine:需要两个任务的结果进行组合(如合并两个查询结果)
  • allOf:需要等待多个任务全部完成(如批量处理)

3.4 异常处理:exceptionally vs handle

核心结论exceptionally只处理异常,handle同时处理成功和异常。

// exceptionally:只处理异常CompletableFuture<String>future=CompletableFuture.supplyAsync(()->{if(Math.random()>0.5){thrownewRuntimeException("随机异常");}return"成功";}).exceptionally(ex->{log.error("处理异常",ex);return"默认值";});// handle:同时处理成功和异常CompletableFuture<String>future2=CompletableFuture.supplyAsync(()->"结果").handle((result,ex)->{if(ex!=null){return"异常处理";}returnresult;});

选择原则

  • 只需要异常处理:使用exceptionally
  • 需要统一处理成功和异常:使用handle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1170328.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java多并发编程】CompletableFuture 使用指南(实战篇):从场景到优化

文章目录一、实战场景&#xff08;Practical Scenarios&#xff09;&#xff1a;从简单到复杂1.1 多数据源并行查询&#xff1a;总耗时约等于最慢的那个&#xff08;性能提升可达数倍&#xff09;1.2 异步任务链式处理&#xff1a;前一个任务的输出作为后一个任务的输入&#x…

【毕业设计】基于SpringBoot+vue的山区农产品供销服务系统的设计与实现(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Keil MDK-ARM 540 超详细下载安装激活教程攻略:嵌入式开发新手零失败教程(2026 实测)

做单片机编程、Cortex-M 内核开发的朋友,肯定绕不开 Keil MDK-ARM—— 这款嵌入式开发神器堪称 “行业标配”,而 5.40 版本更是经典稳定款,兼容绝大多数主流单片机(STM32、NXP、Microchip 等),不管是课程设计、毕…

告别堆叠,拥抱统一:金仓数据库“多模一体”开启文档处理新范式

金仓数据库 MongoDB 兼容版通过“多模融合”架构重塑文档数据库新范式&#xff0c;其核心在于将文档模型深度集成于统一的企业级数据库内核中&#xff0c;实现关系型与文档型数据的统一处理与管理。以下从使用示例、性能对比、内核特性、迁移与高可用、实践案例等方面展开说明&…

Java毕设选题推荐:基于SpringBoot+vue的农产品供应链管理系统设计与开发 山区农产品供销服务系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

基于 Flutter × OpenHarmony 构建高质感专辑封面区域实践

文章目录基于 Flutter OpenHarmony 构建高质感专辑封面区域实践前言背景Flutter OpenHarmony 跨端开发介绍开发核心代码关键实现解析心得总结基于 Flutter OpenHarmony 构建高质感专辑封面区域实践 前言 在音乐类、多媒体类应用中&#xff0c;专辑封面区域往往是用户第一眼…

2026必备!继续教育TOP8AI论文网站测评与推荐

2026必备&#xff01;继续教育TOP8AI论文网站测评与推荐 2026年继续教育AI论文写作工具测评&#xff1a;精准选择&#xff0c;提升效率 随着人工智能技术在学术领域的不断渗透&#xff0c;越来越多的继续教育学习者开始依赖AI工具辅助论文写作。然而&#xff0c;面对市场上琳琅…

程序员如何系统入门Vibe Coding?

在程序员的世界里&#xff0c;我们经常讨论技术栈、算法优化和设计模式&#xff0c;但有一个概念正在悄然改变许多开发者的工作方式——Vibe Coding&#xff08;氛围编程&#xff09;。这不仅仅是一种编码风格&#xff0c;更是一种将环境、心境和创造力融入开发过程的全新方法论…

导师推荐2026 AI论文工具TOP9:继续教育写作全攻略

导师推荐2026 AI论文工具TOP9&#xff1a;继续教育写作全攻略 2026年AI论文工具测评&#xff1a;助力继续教育写作的高效选择 在继续教育领域&#xff0c;撰写高质量的学术论文已成为许多专业人士提升自我、实现职业发展的关键环节。然而&#xff0c;面对繁重的工作任务与有限的…

【实测好用】禁止windows更新工具,一键彻底关闭Win11自动更新工具

你是否厌倦了Windows系统在工作或游戏时突然弹出的“正在更新”提示&#xff1f;虽然微软推送更新是为了安全&#xff0c;但在实际体验中&#xff0c;频繁的强制重启、更新后的驱动不兼容、甚至突如其来的“蓝屏死机”&#xff0c;让无数用户头疼不已。 市面上很多“禁用服务…

Claude Code 插件 Skill-Creator 使用说明

Claude Code 插件 Skill-Creator 使用说明&#xff08;从 0 到生产级&#xff09;如果你已经在用 Claude Code 写代码&#xff0c;却还在一遍遍手敲“请你按 XXX 风格生成代码”“请你遵循我的项目规范”&#xff0c;那你其实浪费了 Claude 80% 的真正能力。 Skill-Creator 的存…

救命神器9个一键生成论文工具,本科生毕业论文救星!

救命神器9个一键生成论文工具&#xff0c;本科生毕业论文救星&#xff01; 论文写作的“救火队员”&#xff0c;你值得拥有 对于许多本科生来说&#xff0c;毕业论文不仅是一场学术能力的考验&#xff0c;更是一次心理和时间上的双重挑战。尤其是在选题、框架搭建、内容撰写以及…

新买的电脑如何禁止WIn10、Win11系统自动更新?一键关闭Windows系统更新!!关闭或禁用windows自动更新工具

微软的强制更新策略虽然是为了安全&#xff0c;但常常打断我们的工作节奏。系统自带的暂停功能最多只能延迟35天&#xff0c;治标不治本。那么&#xff0c;windows10/11怎么关闭自动更新呢&#xff1f; 下面介绍了六种关闭 Windows 10/Windows 11 自动更新的方法&#xff0c;包…

从80%降到10%!实测5个真实有效的降AI率工具,分享免费降AI改写技巧,告别高AI率焦虑症

目前越来越多的同学面临一个问题&#xff1a;AI率太高怎么降&#xff1f; 尤其是越来越多的学校发布公告对AIGC率作出要求&#xff0c;寻找好用的降AIGC方法和工具就成了我这段时间研究的问题。 现在降AI工具越来越多&#xff0c;从免费的到付费的&#xff0c;从低价的到高价…

毕业论文AIGC疑似度太高怎么办?深度评测5个真实有效的降AI神器,手把手教你免费降低AI率

目前越来越多的同学面临一个问题&#xff1a;AI率太高怎么降&#xff1f; 尤其是越来越多的学校发布公告对AIGC率作出要求&#xff0c;寻找好用的降AIGC方法和工具就成了我这段时间研究的问题。 现在降AI工具越来越多&#xff0c;从免费的到付费的&#xff0c;从低价的到高价…

03命题逻辑的推理理论

03命题逻辑的推理理论3种题型 逆向推导法附加前提法:一般结论中出现了蕴含,就会使用附加前提、附加律、化简律归谬法(需要两个或以上的条件时)

免费 vs 付费降AI工具差异在哪?全网核心工具横向对比8款降AI工具,到底哪个才能真正降ai

作为新世纪大学生&#xff0c;不用AI辅助写论文是不可能的&#xff01;可在DDL之前疯狂赶出了初稿&#xff0c;用知网一检测&#xff0c;坏了&#xff01;AI率78%&#xff01; 为了顺利毕业&#xff0c;必须得把AI率降下去...于是乎开始纯手改↓ AI率那是越改越高啊&#xff0…

全网最全的降AI测评:对比5款降AI工具的真实效果,分享免费降AI实操方案

目前越来越多的同学面临一个问题&#xff1a;AI率太高怎么降&#xff1f; 尤其是越来越多的学校发布公告对AIGC率作出要求&#xff0c;寻找好用的降AIGC方法和工具就成了我这段时间研究的问题。 现在降AI工具越来越多&#xff0c;从免费的到付费的&#xff0c;从低价的到高价…

毕业论文AI率过高?别慌!收藏这份免费的降AI工具合集,8款降AIGC率工具帮你有效降低AI率

作为新世纪大学生&#xff0c;不用AI辅助写论文是不可能的&#xff01;可在DDL之前疯狂赶出了初稿&#xff0c;用知网一检测&#xff0c;坏了&#xff01;AI率78%&#xff01; 为了顺利毕业&#xff0c;必须得把AI率降下去...于是乎开始纯手改↓ AI率那是越改越高啊&#xff0…

论文AI率居高不下?2026年最新5款降AI工具实测推荐,附带免费降AI保姆级教程,轻松绕过AI检测

目前越来越多的同学面临一个问题&#xff1a;AI率太高怎么降&#xff1f; 尤其是越来越多的学校发布公告对AIGC率作出要求&#xff0c;寻找好用的降AIGC方法和工具就成了我这段时间研究的问题。 现在降AI工具越来越多&#xff0c;从免费的到付费的&#xff0c;从低价的到高价…