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

CompletableFuture使用详解(IT枫斗者)

CompletableFuture使用详解

简介

概述

  • CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口,并在此基础上进行了丰富的扩展,完美弥补了Future的局限性,同时CompletableFuture实现了对任务编排的能力。借助这项能力,可以轻松地组织不同任务的运行顺序、规则以及方式。从某种程度上说,这项能力是它的核心能力。而在以往,虽然通过CountDownLatch等工具类也可以实现任务的编排,但需要复杂的逻辑处理,不仅耗费精力且难以维护。

  • CompletableFuture的继承结构如下:

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a61HTSe5-1680694141534)(C:%5CUsers%5Cquyanliang%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5C1680692539301.png)]

  • CompletionStage接口定义了任务编排的方法,执行某一阶段,可以向下执行后续阶段。异步执行的,默认线程池是ForkJoinPool.commonPool(),但为了业务之间互不影响,且便于定位问题,强烈推荐使用自定义线程池

  • CompletableFuture中默认线程池如下:

  • // 根据commonPool的并行度来选择,而并行度的计算是在ForkJoinPool的静态代码段完成的
    private static final boolean useCommonPool =(ForkJoinPool.getCommonPoolParallelism() > 1);private static final Executor asyncPool = useCommonPool ?ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
    
  • ForkJoinPool中初始化commonPool的参数 \

  • static {// initialize field offsets for CAS etctry {U = sun.misc.Unsafe.getUnsafe();Class<?> k = ForkJoinPool.class;CTL = U.objectFieldOffset(k.getDeclaredField("ctl"));RUNSTATE = U.objectFieldOffset(k.getDeclaredField("runState"));STEALCOUNTER = U.objectFieldOffset(k.getDeclaredField("stealCounter"));Class<?> tk = Thread.class;……} catch (Exception e) {throw new Error(e);}commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;defaultForkJoinWorkerThreadFactory =new DefaultForkJoinWorkerThreadFactory();modifyThreadPermission = new RuntimePermission("modifyThread");// 调用makeCommonPool方法创建commonPool,其中并行度为逻辑核数-1common = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<ForkJoinPool>() {public ForkJoinPool run() { return makeCommonPool(); }});int par = common.config & SMASK; // report 1 even if threads disabledcommonParallelism = par > 0 ? par : 1;
    }
    

功能

常用方法

  • 依赖关系

    • thenApply():把前面任务的执行结果,交给后面的Function
    • thenCompose():用来连接两个有依赖关系的任务,结果由第二个任务返回
  • and集合关系
    • thenCombine():合并任务,有返回值
    • thenAccepetBoth():两个任务执行完成后,将结果交给thenAccepetBoth处理,无返回值
    • runAfterBoth():两个任务都执行完成后,执行下一步操作(Runnable类型任务)
    or聚合关系
    • applyToEither():两个任务哪个执行的快,就使用哪一个结果,有返回值
    • acceptEither():两个任务哪个执行的快,就消费哪一个结果,无返回值
    • runAfterEither():任意一个任务执行完成,进行下一步操作(Runnable类型任务)
  • 并行执行
    • allOf():当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture
    • anyOf():当任何一个给定的CompletablFuture完成时,返回一个新的CompletableFuture
  • 结果处理
    • whenComplete:当任务完成时,将使用结果(或 null)和此阶段的异常(或 null如果没有)执行给定操作
    • exceptionally:返回一个新的CompletableFuture,当前面的CompletableFuture完成时,它也完成,当它异常完成时,给定函数的异常触发这个CompletableFuture的完成

异步操作

应用场景

结果转换

  • 将上一段任务的执行结果作为下一阶段任务的入参参与重新计算,产生新的结果。

thenApply

  • thenApply接收一个函数作为参数,使用该函数处理上一个CompletableFuture调用的结果,并返回一个具有处理结果的Future对象。

  • 常用使用:

  • public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
    public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
    
  • 具体使用:

  • CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {int result = 100;System.out.println("第一次运算:" + result);return result;
    }).thenApply(number -> {int result = number * 3;System.out.println("第二次运算:" + result);return result;
    });
    

thenCompose

  • thenCompose的参数为一个返回CompletableFuture实例的函数,该函数的参数是先前计算步骤的结果。

  • 常用方法:

  • public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
    public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
    
  • 具体使用:

  • CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(30);System.out.println("第一次运算:" + number);return number;}}).thenCompose(new Function<Integer, CompletionStage<Integer>>() {@Overridepublic CompletionStage<Integer> apply(Integer param) {return CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = param * 2;System.out.println("第二次运算:" + number);return number;}});}});
    

thenApply 和 thenCompose的区别

  • thenApply转换的是泛型中的类型,返回的是同一个CompletableFuture;
  • thenCompose将内部的CompletableFuture调用展开来并使用上一个CompletableFutre调用的结果在下一步的CompletableFuture调用中进行运算,是生成一个新的CompletableFuture。

结果消费

  • 结果处理结果转换系列函数返回一个新的CompletableFuture不同,结果消费系列函数只对结果执行Action,而不返回新的计算值。
  • 根据对结果的处理方式,结果消费函数又可以分为下面三大类:
    • thenAccept():对单个结果进行消费
    • thenAcceptBoth():对两个结果进行消费
    • thenRun():不关心结果,只对结果执行Action

thenAccept

  • 观察该系列函数的参数类型可知,它们是函数式接口Consumer,这个接口只有输入,没有返回值。

  • 常用方法:

  • public CompletionStage<Void> thenAccept(Consumer<? super T> action);
    public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
    
  • 具体使用:

  • CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {int number = new Random().nextInt(10);System.out.println("第一次运算:" + number);return number;}).thenAccept(number ->System.out.println("第二次运算:" + number * 5));
    

thenAcceptBoth

  • thenAcceptBoth函数的作用是,当两个CompletionStage都正常完成计算的时候,就会执行提供的action消费两个异步的结果。

  • 常用方法:

  • public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
    public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
    
  • 具体使用:

  • CompletableFuture<Integer> futrue1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(3) + 1;try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务1结果:" + number);return number;}
    });CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(3) + 1;try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务2结果:" + number);return number;}
    });futrue1.thenAcceptBoth(future2, new BiConsumer<Integer, Integer>() {@Overridepublic void accept(Integer x, Integer y) {System.out.println("最终结果:" + (x + y));}
    });
    

thenRun

  • thenRun也是对线程任务结果的一种消费函数,与thenAccept不同的是,thenRun会在上一阶段 CompletableFuture计算完成的时候执行一个Runnable,而Runnable并不使用该CompletableFuture计算的结果。

  • 常用方法:

  • public CompletionStage<Void> thenRun(Runnable action);
    public CompletionStage<Void> thenRunAsync(Runnable action);
    
  • 具体使用:

  • CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {int number = new Random().nextInt(10);System.out.println("第一阶段:" + number);return number;
    }).thenRun(() ->System.out.println("thenRun 执行"));
    

结果组合

thenCombine

  • 合并两个线程任务的结果,并进一步处理。

  • 常用方法:

  • public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor);
    
  • 具体使用:

  • CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10);System.out.println("任务1结果:" + number);return number;}});
    CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10);System.out.println("任务2结果:" + number);return number;}});
    CompletableFuture<Integer> result = future1.thenCombine(future2, new BiFunction<Integer, Integer, Integer>() {@Overridepublic Integer apply(Integer x, Integer y) {return x + y;}});
    System.out.println("组合后结果:" + result.get());
    

任务交互

  • 线程交互指将两个线程任务获取结果的速度相比较,按一定的规则进行下一步处理

applyToEither

  • 两个线程任务相比较,先获得执行结果的,就对该结果进行下一步的转化操作。

  • 常用方法:

  • public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
    public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
    
  • 具体使用:

  • CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10);try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务1结果:" + number);return number;}});
    CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10);try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务2结果:" + number);return number;}
    });future1.applyToEither(future2, new Function<Integer, Integer>() {@Overridepublic Integer apply(Integer number) {System.out.println("最快结果:" + number);return number * 2;}
    });
    

acceptEither

  • 两个线程任务相比较,先获得执行结果的,就对该结果进行下一步的消费操作。

  • 常用方法:

  • public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
    public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
    
  • 具体使用:

  • CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10) + 1;try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("第一阶段:" + number);return number;}
    });CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(10) + 1;try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("第二阶段:" + number);return number;}
    });future1.acceptEither(future2, new Consumer<Integer>() {@Overridepublic void accept(Integer number) {System.out.println("最快结果:" + number);}
    });
    

runAfterEither

  • 两个线程任务相比较,有任何一个执行完成,就进行下一步操作,不关心运行结果。

  • 常用方法:

  • public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
    public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
    
  • 具体使用:

  • CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(5);try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务1结果:" + number);return number;}
    });CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(5);try {TimeUnit.SECONDS.sleep(number);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务2结果:" + number);return number;}
    });future1.runAfterEither(future2, new Runnable() {@Overridepublic void run() {System.out.println("已经有一个任务完成了");}
    }).join();
    

anyOf

  • anyOf() 的参数是多个给定的 CompletableFuture,当其中的任何一个完成时,方法返回这个 CompletableFuture

  • 常用方法:

  • public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
    
  • 具体使用:

  • Random random = new Random();
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(random.nextInt(5));} catch (InterruptedException e) {e.printStackTrace();}return "hello";
    });CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(random.nextInt(1));} catch (InterruptedException e) {e.printStackTrace();}return "world";
    });
    CompletableFuture<Object> result = CompletableFuture.anyOf(future1, future2);
    

allOf

  • allOf方法用来实现多 CompletableFuture 的同时返回。

  • 常用方法:

  • public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
    
  • 具体使用:

  • CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("future1完成!");return "future1完成!";
    });CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {System.out.println("future2完成!");return "future2完成!";
    });CompletableFuture<Void> combindFuture = CompletableFuture.allOf(future1, future2);try {combindFuture.get();
    } catch (InterruptedException e) {e.printStackTrace();
    } catch (ExecutionException e) {e.printStackTrace();
    }
    
  • CompletableFuture常用方法总结:

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1mWmBu8C-1680694141535)(C:%5CUsers%5Cquyanliang%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5C1680693984873.png)]

  • 注:CompletableFuture中还有很多功能丰富的方法,这里就不一一列举。

使用案例

实现最优的“烧水泡茶”程序

  • 著名数学家华罗庚先生在《统筹方法》这篇文章里介绍了一个烧水泡茶的例子,文中提到最优的工序应该是下面这样:

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VW2F4P5T-1680694141536)(C:%5CUsers%5Cquyanliang%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5C1680694045463.png)]

  • 对于烧水泡茶这个程序,一种最优的分工方案:用两个线程 T1 和 T2 来完成烧水泡茶程序,T1 负责洗水壶、烧开水、泡茶这三道工序,T2 负责洗茶壶、洗茶杯、拿茶叶三道工序,其中 T1 在执行泡茶这道工序时需要等待 T2 完成拿茶叶的工序。

基于Future实现

  • public class FutureTaskTest{public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建任务T2的FutureTaskFutureTask<String> ft2 = new FutureTask<>(new T2Task());// 创建任务T1的FutureTaskFutureTask<String> ft1 = new FutureTask<>(new T1Task(ft2));// 线程T1执行任务ft2Thread T1 = new Thread(ft2);T1.start();// 线程T2执行任务ft1Thread T2 = new Thread(ft1);T2.start();// 等待线程T1执行结果System.out.println(ft1.get());}
    }// T1Task需要执行的任务:
    // 洗水壶、烧开水、泡茶
    class T1Task implements Callable<String> {FutureTask<String> ft2;// T1任务需要T2任务的FutureTaskT1Task(FutureTask<String> ft2){this.ft2 = ft2;}@Overridepublic String call() throws Exception {System.out.println("T1:洗水壶...");TimeUnit.SECONDS.sleep(1);System.out.println("T1:烧开水...");TimeUnit.SECONDS.sleep(15);// 获取T2线程的茶叶String tf = ft2.get();System.out.println("T1:拿到茶叶:"+tf);System.out.println("T1:泡茶...");return "上茶:" + tf;}
    }
    // T2Task需要执行的任务:
    // 洗茶壶、洗茶杯、拿茶叶
    class T2Task implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println("T2:洗茶壶...");TimeUnit.SECONDS.sleep(1);System.out.println("T2:洗茶杯...");TimeUnit.SECONDS.sleep(2);System.out.println("T2:拿茶叶...");TimeUnit.SECONDS.sleep(1);return "龙井";}
    }
    

基于CompletableFuture实现

  • public class CompletableFutureTest {public static void main(String[] args) {//任务1:洗水壶->烧开水CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {System.out.println("T1:洗水壶...");sleep(1, TimeUnit.SECONDS);System.out.println("T1:烧开水...");sleep(15, TimeUnit.SECONDS);});//任务2:洗茶壶->洗茶杯->拿茶叶CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {System.out.println("T2:洗茶壶...");sleep(1, TimeUnit.SECONDS);System.out.println("T2:洗茶杯...");sleep(2, TimeUnit.SECONDS);System.out.println("T2:拿茶叶...");sleep(1, TimeUnit.SECONDS);return "龙井";});//任务3:任务1和任务2完成后执行:泡茶CompletableFuture<String> f3 = f1.thenCombine(f2, (__, tf) -> {System.out.println("T1:拿到茶叶:" + tf);System.out.println("T1:泡茶...");return "上茶:" + tf;});//等待任务3执行结果System.out.println(f3.join());}static void sleep(int t, TimeUnit u){try {u.sleep(t);} catch (InterruptedException e) {}}
    }
    

相关文章:

CompletableFuture使用详解(IT枫斗者)

CompletableFuture使用详解 简介 概述 CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口&#xff0c;并在此基础上进行了丰富的扩展&#xff0c;完美弥补了Future的局限性&#xff0c;同时CompletableFuture实现了对任务编排的能力。借助这项能力…...

4.15--设计模式之创建型之责任链模式(总复习版本)---脚踏实地,一步一个脚印

一、什么是责任链模式&#xff1a; 责任链模式属于行为型模式&#xff0c;是为请求创建了一个接收者对象的链&#xff0c;将链中每一个节点看作是一个对象&#xff0c;每个节点处理的请求均不同&#xff0c;且内部自动维护一个下一节点对象。 当一个请求从链式的首端发出时&a…...

STM32+W5500实现以太网通信

STM32系列32位微控制器基于Arm Cortex-M处理器&#xff0c;旨在为MCU用户提供新的开发自由度。它包括一系列产品&#xff0c;集高性能、实时功能、数字信号处理、低功耗/低电压操作、连接性等特性于一身&#xff0c;同时还保持了集成度高和易于开发的特点。本例采用STM32作为MC…...

全网最详细,Jmeter性能测试-性能基础详解,终成测试卷王(一)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 发起请求 发起HTTP…...

人工智能概述

一、人工智能发展必备三要素 算法 数据 算力 CPU、GPU、TPU 计算力之CPU、GPU对比&#xff1a; CPU主要适合I\O密集型任务GPU主要适合计算密集型任务 什么样的程序适合在GPU上运行&#xff1f; 计算密集型的程序 所谓计算密集型(Compute-intensive)的程序&#xff0c;就是…...

API接口安全—webservice、Swagger、WEBpack

API接口安全—webservice、Swagger、WEBpack1. API接口介绍1.1. 常用的API接口类1.1.1. API接口分类1.1.1.1. 类库型API1.1.1.2. 操作系统型API1.1.1.3. 远程应用型API1.1.1.4. WEB应用型API1.1.1.5. 总结1.1.2. API接口类型1.1.2.1. HTTP类接口1.1.2.2. RPC类接口1.1.2.3. web…...

从前M个字母中取N个的无重复排列 [2*+]

目录 从前M个字母中取N个的无重复排列 [2*+] 程序设计 程序分析 从前M个字母中取N个的无重复排列 [2*+] 输出从前M个字母中取N个的无重复字母排列 Input 输入M N 1<=M=10, N<=M Output 按字典序输出排列 Sample Input 4 2 Sample Output A B A C A D B A B C B …...

ES forceMerge 强制段合并为什么会提升检索性能?

根据以前的测试&#xff0c;forceMerge段合并&#xff0c;将段的个数合并成一个。带来了将近一倍的性能提升&#xff0c;测试过程文档&#xff08;请参考我的另外一篇文章&#xff09;&#xff1a;ES优化实战- forceMerge搜索提升测试报告_es forcemerge_水的精神的博客-CSDN博…...

macOS Ventura 13.3.1 (22E261) Boot ISO 原版可引导镜像

本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Linux 中创建可引导介质。 macOS Ventura 13.3.1 为 Mac 提供下…...

html+css+JavaScript+json+servlet的社区系统(手把手教学)

目录 课前导读&#xff1a; 一、系统前期准备 二、前端代码的编写 三、登陆页面简介 四、注册页面 五、社区列表页 六、社区详情页 七、社区发帖页 八、注销 九、访问链接 登陆页面http://175.178.20.77:8080/java106_blog_system/login.html 总结&#xff1a; 课前…...

UI Toolkit(1)

UI ToolkitUI Toolkit界面画布设置背景制作UI布局UI Toolkit界面 在Unity 2021LTS版本之后UI Toolkit也被内置在Unity中&#xff0c;Unity有意的想让UI Toolkit 成为UI的主要搭建方式&#xff0c;当然与UGUI相比还是有一定的差别。他们各有有点&#xff0c;这次我们就开始介绍…...

vLive带你走进虚拟直播世界

虚拟直播是什么&#xff1f; 虚拟直播是基于5G实时渲染技术&#xff0c;在绿幕环境下拍摄画面&#xff0c;通过实时抠像、渲染与合成&#xff0c;再推流到直播平台的一种直播技术。尽管这种技术早已被影视工业所采用&#xff0c;但在全民化进程中却是困难重重&#xff0c;面临…...

初谈 ChatGPT

引子 最近&#xff0c;小编发现互联网中的大 V 突然都在用 ChatGPT 做宣传&#xff1a;“ChatGPT不会淘汰你&#xff0c;能驾驭ChatGPT的人会淘汰你”、“带领一小部分人先驾驭ChatGPT”。 确实&#xff0c;ChatGPT这个新生事物&#xff0c;如今被视为蒸汽机、电脑、iPhone 般的…...

JAVA练习103-螺旋矩阵

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 4月9日练习内容 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目-螺…...

RecvByteBufAllocator内存分配计算

虽然了解了整个内存池管理的细节&#xff0c;包括它的内存分配的具体逻辑&#xff0c;但是每次从NioSocketChannel中读取数据时&#xff0c;应该分配多少内存去读呢&#xff1f; 例如&#xff0c;客户端发送的数据为1KB , 应该分配多少内存去读呢&#xff1f; 例如&#xff1a;…...

图数据结构与算法

什么是图数据的结构 图是由顶点和边组成的非线性数据结构。顶点有时也称为节点,边是连接图中任意两个节点的线或弧。更正式地说,图由一组顶点 ( V ) 和一组边 ( E ) 组成。该图由 G(E, V) 表示。 图的组成部分 顶点:顶点是图的基本单位。有时,顶点也称为顶点或节点。每个节…...

科普:c语言与C++的区别

C语言和C语言是两种广泛使用的编程语言&#xff0c;尽管它们非常相似&#xff0c;但它们在某些方面也存在不同之处。本文将详细介绍C语言和C语言的区别。 1. 编程范式 C语言是一种过程式编程语言&#xff0c;它的设计目标是为了编写操作系统和其他系统级编程。C语言是一种面向…...

流量整形(GTS和LR)

Generic Traffic Shaping通用流量整形 通用流量整形(简称GTS)可以对不规则或不符合预定流量特性的流量进行整形,以保证网络上下游之间的带宽匹配,避免拥塞发生。 GTS与CAR一样,都采用了令牌桶技术来控制流量。GTS与CAR的主要区别在于:利用CAR进行报文流量控制时,…...

Java接口详细讲解

目录 Java接口概念 Java接口主要有以下特点 Java接口的具体作用 定义接口 实现接口 接口继承 默认方法 静态方法 Java接口概念 Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 …...

元宇宙地产暴跌,林俊杰亏麻了

文/章鱼哥出品/陀螺财经随着元宇宙的兴起&#xff0c;元宇宙地产曾一度被寄予厚望&#xff0c;成为各大投资者追捧的对象。然而&#xff0c;最近的一次元宇宙地产价值暴跌再次提醒我们&#xff0c;高收益背后可能伴随着高风险。根据元宇宙分析平台WeMeta的数据显示&#xff0c;…...

什么是瀑布流布局?瀑布流式布局的优缺点

瀑布流又称瀑布流式布局&#xff0c;是一种多列等宽不等高的一种页面布局方式。 视觉表现为参差不齐的多栏布局。随着页面滚动条向下滚动&#xff0c;这种布局会不断加载数据并附加至当前的尾部。 是一种多列等宽不等高的一种页面布局方式&#xff0c;用于图片比较复杂&#…...

给您的 MongoDB 定期做个体检:MongoDB 诊断

新钛云服已累计为您分享739篇技术干货接下来的一些列文章会为大家介绍日常工作中常用的 NoSQL 产品 MongoDB。主要涉及到&#xff1a;MongoDB 的安装及基本使用 MongoDB 文档查询 MongoDB 复制集 MongoDB 分片集群的介绍及搭建 MongoDB 安全加密 MongoDB 诊断我们会用…...

【云原生进阶之容器】第五章容器运行时5.8--容器热迁移

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述第一章Docker核心技术1.2节——Linux容器LXC第一章Docker核心技术1.3节——命名空间Namespace第一章Docker核心技术1.4节——chroot技术第一章Docker核心技术1.5.1节——cgroup综述...

react框架的简单认识

React框架 众所周知&#xff0c;React与Vue&#xff0c;Angular被前端开发人员称为前端的三大框架。在如今&#xff0c;React和Vue相对于老牌的Angular&#xff0c;它们的表现更为出色&#xff0c;常常被各大公司使用。但其中React的技术难度要稍稍大于Vue&#xff0c;不过为了…...

IDEA的基本使用

IDEA的基本使用IDEA的基本使用1 IDEA概述2 IDEA的下载和安装2.1 下载2.2 安装3 IDEA中层级结构介绍3.1 结构分类3.2 结构介绍project&#xff08;项目、工程&#xff09;module&#xff08;模块&#xff09;package&#xff08;包&#xff09;class&#xff08;类&#xff09;3…...

【MySQL】实验八 触发器与存储过程

文章目录 1. 创建商品价格修改记录表2. 创建触发器,当更改商品价格(price列)时,记录价格3. SQL触发器:插入新员工时,同步更新部门表相应人数4. SQL触发器:删除学生数据5. SQL触发器:创建成绩表插入触发器6. SQL存储过程:查询订单7. SQL存储过程:建立存储过程,查询课程…...

Mockito5.2.0学习

Mockito是mocking框架&#xff0c;它让你用简洁的API做测试。而且Mockito简单易学&#xff0c;它可读性强和验证语法简洁。 Mockito 是一个针对 Java 的单元测试模拟框架&#xff0c;它与 EasyMock 和 jMock 很相似&#xff0c;都是为了简化单元测试过程中测试上下文 ( 或者称之…...

用指针实现内存动态分配

导引&#xff1a;已知&#xff1a;变量在使用前必须被定义且安排好存储空间。且变量有这么一些分类&#xff1a;全局变量、静态局部变量【它们的储存一般是在编译时确定&#xff0c;在程序开始执行前完成。】自动变量【在执行进入变量定义所在的复合语句时为它们分配存储&#…...

DBSCAN聚类算法及Python实现

DBSCAN聚类算法 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;可以将数据点分成不同的簇&#xff0c;并且能够识别噪声点&#xff08;不属于任何簇的点&#xff09;。 DBSCAN聚类算法的基…...

风光及负荷多场景随机生成与缩减

目录 1 主要内容 计算模型 场景生成与聚类方法应用 2 部分程序 3 程序结果 4 程序链接 1 主要内容 该程序方法复现了《融合多场景分析的交直流混合微电网多时间尺度随机优化调度策略》3.1节基于多场景技术的随机性建模部分&#xff0c;该部分是随机优化调度的重要组成部分…...