Java中CompletableFuture 异步编排的基本使用

news2024/11/16 5:55:17

一、前言

        在复杂业务场景中,有些数据需要远程调用,导致查询时间缓慢,影响以下代码逻辑运行,并且这些浪费时间的逻辑与以后的请求并没有关系,这样会大大增加服务的时间。

          假如商品详情页的每个查询,需要如下标注的时间才能完成 。那么,用户需要 5.5s 后才能看到商品详情页的内容。很显然是不能接受的。 如果有多个线程同时完成这 6 步操作,也许只需要 1.5s 即可完成响应。  

 

        在 Java 8 , 新增加了一个包含 50 个方法左右的类 : CompletableFuture ,提供了非常强大的 Future 的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以 通过回调的方式处理计算结果,并且提供了转换和组合 CompletableFuture 的方法。 CompletableFuture 类实现了 Future 接口,所以你还是可以像以前一样通过 `get` 方法阻塞或 者轮询的方式获得结果,但是这种方式不推荐使用。 CompletableFuture 和 FutureTask 同属于 Future 接口的实现类,都可以获取线程的执行结果。

1、创建异步对象

CompletableFuture 提供了四个静态方法来创建一个异步操作。

 

public static Completab1eFuture runAsync(Runnable runnable)
public static completableFuturecVoid> runAsync(Runnable runnable,Executor executor)
public static CompletableFuture supplyAsync(Suppliersupplier)
public static CompletableFuturecU> supplyAsync(Supplier supplier,Executor executor)
1 runXxxx 都是没有返回结果的, supplyXxx 都是可以获取返回结果的
2 、可以传入自定义的线程池,否则就用默认的线程池;
3、Async代表异步方法

 

1.1 runAsync 不带返回值

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:"+Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行结果...."+i);
        }, executor);
    }
}

1.2 supplyAsync 带返回值 

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("运行结果...." + i);
            return i;
        }, executor);

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
}

 2、计算完成时回调方法

public completableFuture whencomplete(BiConsumer<? super T,? super Throwable> action);
public CompletableFuturewhenCompleteAsync(BiConsumer <? super T,? super Throwable> action);
public completableFuture whenCompleteAsync(BiConsumer<? super T,? super Throwable> action,Executor executor);
public completableFutureexceptionally(Function<Throwable,? extends T> fn);
whenComplete可以处理正常和异常的计算结果,exceptionally处理异常情况。
whenComplete 和 whenCompleteAsync 的区别:
whenComplete: 是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync: 是执行把 whenCompleteAsync 这个任务继续提交给线程池
来进行执行。
方法不以 Async 结尾, 意味着 Action 使用相同的线程执行, 而 Async 可能会使用其他线程执行(如果是使用相同的线程池, 也可能会被同一个线程选中执行)

2.1 whenCompleteAsync 完成回调 (没有异常情况情况)

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).whenCompleteAsync((res, exception) -> {
            System.out.println("异步任务完成....感知到返回值为:"+res+"异常:"+exception);
        },executor);

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
}

 有异常情况

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 0;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).whenCompleteAsync((res, exception) -> {
            System.out.println("异步任务完成....感知到返回值为:"+res+"异常:"+exception);
        },executor);

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
}

此处虽然得到了异常信息但是没有办法修改返回数据,使用exceptionally自定义异常时的返回值 

 2.2 exceptionally 异常感知及处理

异常情况

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 0;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).whenCompleteAsync((res, exception) -> {
            System.out.println("异步任务完成....感知到返回值为:"+res+"异常:"+exception);
        },executor).exceptionally(throwable -> {
            return 0;
        });

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
}

 无异常,情况正常返回不会进exceptionally

public class ThreadTest {
    //        ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(  5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(  100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).whenCompleteAsync((res, exception) -> {
            System.out.println("异步任务完成....感知到返回值为:"+res+"异常:"+exception);
        },executor).exceptionally(throwable -> {
            return 0;
        });

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
}

2.3 最终处理 handle 方法

和 complete 一样, 可对结果做最后的处理(可处理异常),可改变返回值。

总结:使用R apply(T t, U u); 可以感知异常,和修改返回值的功能。

public completionStage handle(BiFunction<? super T,Throwable,? extends U> fn);
public completionStagehandleAsync(BiFunction<? super T,Throwable,? extends U> fn);
public > CompletionStage handleAsync(BiFunction<? super T,Throwable,? extends U> fn,Executor executor ) ;

 有异常情况

	public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 0;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).handleAsync((res, throwable) -> {
            if (res!=null){
                return res*2;
            }
            if (throwable!=null){
                System.out.println("出现异常"+throwable.getMessage());
                return -1;
            }
            return 0;
        },executor);

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }

无异常情况 

	public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 12 / 6;
            System.out.println("运行结果...." + i);
            return i;
        }, executor).handleAsync((res, throwable) -> {
            if (res!=null){
                return res*2;
            }
            if (throwable!=null){
                System.out.println("出现异常"+throwable.getMessage());
                return -1;
            }
            return 0;
        },executor);

        Integer integer = supplyAsync.get();
        System.out.println("返回数据:"+integer);
    }
2.3.1总结 

总结:一般用handle,因为whencomplete如果异常不能给定默认返回结果,需要再调用exceptionally,而handle可以

该方法作用:获得前一任务的返回值【自己也可以是异步执行的】,也可以处理上一任务的异常,调用exceptionally修改前一任务的返回值【例如异常情况时给一个默认返回值】而handle方法可以简化操作


以下用法大致相同,只列举具体方法 

 2.4 线程串行化方法

public CompletableFuture thenApply(Function<? super T,? extends U> fn)
public Completab1eFuture thenApplyAsync(Function<? super T,? extends U> fn)
public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn,Executor executor)

public completionstage thenAccept(Consumer<? super T> action);
public completionStage thenAcceptAsync(Consumer<? super T> action);
public CompletionStagecVoid> thenAcceptAsync(Consumer<? super T> action,Executor executor);

public Completionstage thenRun(Runnable action);
public Completionstage thenRunAsync(Runnable action);
public completionStage thenRunAsync(Runnable action,Executor executor);

 thenApply:继续执行,感知上一任务的返回结果,并且自己的返回结果也被下一个任务所感知
thenAccept:继续执行,接受上一个任务的返回结果,自己执行完没有返回结果
thenRun:继续执行,不接受上一个任务的返回结果,自己执行完也没有返回结果
以上都要前置任务成功完成。
Function<? super T,? extends U>
T: 上一个任务返回结果的类型
U: 当前任务的返回值类型

 2.5 两任务组合 - 都要完成

public <U,V> CompletableFuture thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);

public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);

public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor);

public CompletableFuture thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);

public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);

public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor);

public CompletableFuture runAfterBoth(CompletionStage<?> other, Runnable action);

public CompletableFuture runAfterBothAsync(CompletionStage<?> other, Runnable action);

public CompletableFuture runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor);

thenCombine:组合两个future,获取前两个future的返回结果,并返回当前任务的返回值
thenAcceptBoth:组合两个future,获取前两个future任务的返回结果,然后处理任务,没有返回值。
runAfterBoth:组合两个future,不需要获取之前任务future的结果,只需两个future处理完任务后,处理该任务。

 2.5.1 runAfterBothAsync
 public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务一线程开始:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("任务一运行结束...." + i);
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务二线程开始:" + Thread.currentThread().getName());
            System.out.println("任务二运行结束....");
            return "hello";
        }, executor);

        future01.runAfterBothAsync(future02,() -> {
            System.out.println("任务三开始...");
        });

        System.out.println("返回数据:");
    }

 2.6 两个任务 - 一个完成

  1.  applyToEither: 两个任务有一个执行完成, 获取它的返回值, 处理任务并有新的返回值。
  2. acceptEither: 两个任务有一个执行完成, 获取它的返回值, 处理任务, 没有新的返回值。
  3. runAfterEither: 两个任务有一个执行完成, 不需要获取 future 的结果, 处理任务, 也没有返回值。

2.7 多任务组合 

//allOf: 等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
    return andTree(cfs, 0, cfs.length - 1);
}

//anyOf: 只要有一个任务完成
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
    return orTree(cfs, 0, cfs.length - 1);
}
 2.7.1 allOf
public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务一线程开始:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("任务一运行结束...." + i);
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务二线程开始:" + Thread.currentThread().getName());

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务二运行结束....");
            return "hello";
        }, executor);
        CompletableFuture<Object> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务三线程开始:" + Thread.currentThread().getName());

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务三运行结束....");
            return "hello2";
        }, executor);

        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();//等待所有任务完成
        System.out.println("返回数据:");
    }
 2.7.2 anyOf
public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务一线程开始:" + Thread.currentThread().getName());
            int i = 12 / 2;
            System.out.println("任务一运行结束...." + i);
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务二线程开始:" + Thread.currentThread().getName());

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务二运行结束....");
            return "hello";
        }, executor);
        CompletableFuture<Object> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务三线程开始:" + Thread.currentThread().getName());

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务三运行结束....");
            return "hello2";
        }, executor);

         CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);
        anyOf.get();//等待其中之一任务完成
        System.out.println("返回数据:");
    }

 

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

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

相关文章

基于sprinmgboot实习管理系统源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;实习管理也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;而实习管理…

老铁,请收藏!IT人必备13个在线工具

本文根据很多很多大牛程序员分享&#xff0c;还请教了身边的资深职场人&#xff0c;给大家总结了一份大咖推荐的超实用网站合集&#xff0c;包含工具类和提效类&#xff0c;赶上要做年终汇报和来年计划的档口&#xff0c;80%你都用得上&#xff01; 先收藏&#xff0c;有需要随…

“第四个中国人民警察节”细语

今&#xff08;2024年1月10日&#xff09;天&#xff0c;是第四个中国人民警察节&#xff0c;本“人民体验官”推广人民日报官方微博文化产品《一起致敬人民警察&#xff01;》。 图&#xff1a;来源“人民体验官”推广平台 笔者认同“平安的密码叫110”这个洽当比喻。因为人民…

Android App打包加固后的APK无法安装问题

最近开发的一个应用要上架&#xff0c;正常流程打完包后去加固&#xff0c;由于以前一直用的是360的加固助手&#xff0c;这里开始也是选择用它。 使用360加固&#xff1a; 问题一、开始出现的问题是说应用未签名无法加固&#xff0c;我明明是签名后打的包&#xff0c;怎么会…

世邦 IP网络对讲广播系统 getjson.php接口存在任意文件读取漏洞

产品简介 SPON世邦IP网络对讲广播系统是一种先进的通信解决方案&#xff0c;旨在提供高效的网络对讲和广播功能。 漏洞概述 SPON世邦IP网络对讲广播系统getjson.php接口处存在任意文件读取漏洞&#xff0c;未经身份验证的攻击者可利用此漏洞读取敏感文件。 指纹识别 fofa:…

ROS2——发布和订阅

现在我们以主题 int_topic 和发布者 publisher_node 和订阅者 subscriber_node 为例子进行展开。 头文件 在调用各种消息类型时&#xff0c;需要先引用头文件&#xff0c;才能成功声明某一个消息类型的变量。 我们在写头文件时&#xff0c;需要将该类成员的大写字母转换成小写…

文献阅读1

A Hierarchical Representation Network for Accurate and Detailed Face Reconstruction from In-The-Wild Images 会议/期刊&#xff1a;CVPR 2023&#xff1b;阿里达摩院&#xff1b;Biwen Lei 概述&#xff1a;这是一篇单张图片三维人脸重建的论文&#xff0c;这篇论文的…

LeetCode-棒球比赛(682)

题目描述&#xff1a; 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录的第…

STM32 使用 DS18B20 温度传感器实现环境温度监测

为了实现环境温度监测系统&#xff0c;我们可以利用STM32微控制器和DS18B20数字温度传感器。在本文中&#xff0c;我们将介绍如何通过STM32微控制器读取DS18B20传感器的温度数据&#xff0c;并展示一个简单的示例代码。 1. 系统概述 环境温度监测系统旨在使用DS18B20数字温度…

ssm基于Web的汽车客运订票系统的设计与实现论文

毕业设计&#xff08;论文&#xff09; 汽车客运订票系统 姓 名 ______________________ 学 号 ______________________ 班 级 ______________________ 专 业 ______________________ 院 部 ______________________ 指导教师 ______________________ 年 月 日 目 录 目 录 …

数据库管理-第130期 JSON二元性(20240109)

数据库管理130期 2024-01-09 第130期 JSON二元性&#xff08;20240109&#xff09;1 简介2 关系型表和JSON存储的优劣3 Oracle JSON关系型二元性视图总结 第130期 JSON二元性&#xff08;20240109&#xff09; 上周&#xff0c;又双叒飞了一趟上海&#xff0c;也是2024年第一飞…

10个最容易被忽视的 FastAPI 实用功能

FastAPI是一种现代、高性能的Python Web框架&#xff0c;用于构建Web应用程序和API。 它基于Python的异步编程库asyncio和await语法&#xff0c;以及类型注解和自动文档生成等特性&#xff0c;提供了快速、易用和可靠的开发体验&#xff0c;接下来本文将介绍10项被忽视的FastA…

设计模式篇章(3)——七种结构型模式

结构型设计模式主要思考的是如何将对象进行合理的布局来组成一个更大的功能体或者结构体&#xff0c;这个现在讲有点抽象&#xff0c;用大白话讲就是利用现有的对象进行组合或者配合&#xff0c;使得组合后的这个系统更加好。好是相对于不使用设计模式&#xff0c;按照自己的堆…

分布式全局id

分布式全局id snowflake 算法是 twitter 开源的分布式 id 生成算法&#xff0c;采用 Scala 语言实现&#xff0c;是把一个 64 位的 long 型的 id&#xff0c;1 个 bit 是不用的&#xff0c;用其中的 41 bits 作为毫秒数&#xff0c;用 10 bits 作为工作机器 id&#xff0c;12 …

Linux权限2

相关命令 chown [用户名] [文件]​ 更改文件拥有者&#xff08;加sudo强制更改&#xff09; chown [拥有者]:[所属组] [文件] 更改文件拥有者和所属组&#xff08;root权限下&#xff09; chgrp [用户名] [文件] 更改文件所属组 文件类型 输入ls或ll显示的文件&#xff…

扒一扒Go语言中的“语法糖”

概 述 最近学习Golang语言的过程中&#xff0c;我发现Golang&#xff08;后面简称Go&#xff09;中的语法糖还蛮多的&#xff0c;有些语法糖还让会让人很懵逼。那么接下来&#xff0c;让我以一个曾经的 Java CURD boy&#xff0c;来说一说 Go 中的语法糖。 语法糖定义 语法糖…

谓词-量词、主析取、主和取范式、前束范式、推理证明

这部分内容&#xff0c;主要需要掌握谓词推理&#xff0c;而前提是掌握将自然语言符号化为谓词、用量词来限定辖域&#xff0c;量词的消去、剩下就是推理过程。还需要掌握的是主析取、主和取范式和前束范式。 存在量词∃&#xff1a;至少有一个 全称量词∀&#xff1a;全都是…

python爬取诗词名句网-三国演义,涉及知识点:xpath,requests,自动识别编码,range

页面源代码: <!DOCTYPE html> <html lang="zh"> <head><script src="https://img.shicimingju.com/newpage/js/all.js"></script><meta charset="UTF-8"><title>《三国演义》全集在线阅读_史书典籍_…

ThreadLocal如何使用详解

ThreadLocal概述&#xff1a; ThreadLocal是Java中的一个线程局部变量工具类&#xff0c;它提供了一种在多线程环境下&#xff0c;每个线程都可以独立访问自己的变量副本的机制。ThreadLocal中存储的数据对于每个线程来说都是独立的&#xff0c;互不干扰。 使用场景&#xff1a…

介绍几种常见的质数筛选法

质数筛选法 1.暴力筛选法 :smirk:2.普通优化 :rofl:3.埃氏筛法:cold_sweat:4.线性筛选法:scream: 质数&#xff1a;除了1和他本身没有其它因数的正整数就是质数。1不是质数&#xff0c;2是质数。 1.暴力筛选法 &#x1f60f; 原理 求x的质数&#xff0c;令y从2到 x \sqrt[]{x…