Java并发编程之CompletableFuture详解

Java异步编程利器:CompletableFuture详解 ‌CompletableFuture‌是Java 8中引入的一个类,它实现了Future和CompletionStage接口,用于支持异步编程和非阻塞操作。CompletableFuture提供了丰富的API,使得并发任务的处理变得简单而高效,能够轻松创建、组合和链式调用异步操作,无需关心底层线程管理,从而提升了程序的响应速度和资源利用率‌。 阅读详情

1、Futuru接口和Callable接口

  • Future接口定义了操作异步任务执行的方法,如:获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、是否执行完毕等
    在这里插入图片描述
  • Callable接口中定义了需要有返回结果的任务 要执行的方法,如:主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,过一段时间才会去获取子任务的执行结果
    在这里插入图片描述
    实现Callable接口中的call(),返回方法计算的结果,或抛出异常

2、FutureTask

在这里插入图片描述
代码示例:

  public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException{
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            System.out.println("-----come in FutureTask");
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            return ThreadLocalRandom.current().nextInt(100);
        });

        Thread t1 = new Thread(futureTask,"t1");
        t1.start();

        //3秒钟后才出来结果,还没有计算你提前来拿(只要一调用get方法,对于结果就是不见不散,会导致阻塞)
        //System.out.println(Thread.currentThread().getName()+"\t"+futureTask.get());

        //3秒钟后才出来结果,我只想等待1秒钟,过时不候
        System.out.println(Thread.currentThread().getName()+"\t"+futureTask.get(1L,TimeUnit.SECONDS));

        System.out.println(Thread.currentThread().getName()+"\t"+" run... here");

    }
  • get(): 一旦调用get()方法,不管是否计算完成都会导致阻塞
 public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            System.out.println("-----come in FutureTask");
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            return ""+ ThreadLocalRandom.current().nextInt(100);
        });

        new Thread(futureTask,"t1").start();

        System.out.println(Thread.currentThread().getName()+"\t"+"线程完成任务");

        /**
         * 用于阻塞式获取结果,如果想要异步获取结果,通常都会以轮询的方式去获取结果
         */
        while (true){
            if(futureTask.isDone()){
                System.out.println(futureTask.get());
                break;
            }
        }
    }
  • isDone()轮询
    • 轮询的方式会耗费无谓的CPU资源,且未必能及时地得到计算结果.
    • 如果想要异步获取结果,通常都会以轮询的方式去获取结果。尽量不要阻塞

3、CompletableFuture

CompletableFuture实现了Future,CompletionStage两个接口,故CompletableFuture功能更加强大
在这里插入图片描述

  • CompletableFuture
    在这里插入图片描述

  • CompletionStage

    • CompletionStage代表异步计算过程中的某个阶段,一个阶段完成以后可能会触发另外一个阶段,有些类似Linux系统的管道分隔符传参数
    • 一个阶段的计算执行可以是一个Function,Consumer或者Runnable
    • 一个阶段的执行可能是被单个阶段计算完成后触发,也可能是由多个阶段一起触发
      在这里插入图片描述
  • CompletionStage 接口中的方法比较多,CompletableFuture 的函数式能力就是这个接口赋予的。从这个接口的方法参数你就可以发现其大量使用了 Java8 引入的函数式编程。

4、CompletableFuture核心的四个静态方法

  • runAsync 无 返回值
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)  
  • supplyAsync 有 返回值
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)
  • 没有指定Executor的方法,直接使用默认的ForkJoinPool.commonPool() 作为它的线程池执行异步代码
  • 如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码
  static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 5, 10L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
private static void testSimpleCompletableFuture() throws InterruptedException, ExecutionException {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        System.out.println(Thread.currentThread().getName() + "\t  is coming in ...");
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(Thread.currentThread().getName() + "\t task was finished!");
    });
   // },poolExecutor);  
    // 如果使用了自行创建的线程池,则使用自定义的或者特别指定的线程池执行异步代码
    System.out.println(future.get());  // get方法返回null,因为runAsync方法无返回值
}
ForkJoinPool.commonPool-worker-1	  is coming in ...
ForkJoinPool.commonPool-worker-1	 task was finished!
null

同上,将runAsync方法改为supplyAsync方法,并返回一个整数类型的变量

  static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 5, 10L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
private static void testSupplyAsync() throws InterruptedException, ExecutionException {
    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread().getName() + "\t  is coming in ... supplyAsync");
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName() + "\t task was finished!");
        //  return ThreadLocalRandom.current().nextInt(100);
        return Runtime.getRuntime().availableProcessors();
    });
   // },poolExecutor);

    System.out.println(future.get());  // get方法返回null,因为runAsync方法无返回值
}
  • 输出结果:
ForkJoinPool.commonPool-worker-1	  is coming in ... supplyAsync
ForkJoinPool.commonPool-worker-1	 task was finished!
8

5、减少阻塞和轮询

  • 从Java8开始引入了CompletableFuture,它是Future的功能增强版,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法
 private static void testWhenCompleteAndExceptionally() {
        CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
            //主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:暂停3秒钟线程
            long result = ThreadLocalRandom.current().nextLong(100);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("异步任务计算完成,结果为:" + result);
            if (result > 5) {
                int i = 1 / 0;
            }
            return result;
        }).whenComplete((res, err) -> {
            if (err == null) {
                System.out.println("异步任务执行正常,其结果为:" + res);
            }
        }).exceptionally(e -> {
            System.out.println("exceptionally,异步任务执行异常:" + e.getCause() + "< --- >" + e.getMessage());

            return Runtime.getRuntime().freeMemory();
        });
        System.out.println(Thread.currentThread().getName() + " task was finished! ...");
        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:暂停3秒钟线程
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

输出结果:

main task was finished! ...
异步任务计算完成,结果为:39
exceptionally,异步任务执行异常:java.lang.ArithmeticException: / by zero< --- >java.lang.ArithmeticException: / by zero
  • 小总结
  • 异步任务不管是正常结束,还是出现异常,都会自动回调某个方法
  • 主线程设置好回调函数后,不再关心异步任务的执行,异步任务之间可以顺序执行

6、电商网站的比价需求案例

  • 对于分布式微服务的调用,按照实际业务,如果是无关联step by step的业务,可以尝试是否可以多箭齐发,同时调用。我们去比同一个商品在各个平台上的价格,要求获得一个清单列表,分别同时或异步查询某个商品在各大商城中的价格,查完京东查淘宝,查完淘宝查天猫…
  • 实现方法如下:
    代码实现1(逐个查询):
class Emall {

    @Getter
    private String emallName;

    public Emall(String emallName) {
        this.emallName = emallName;
    }

    // 生成随机数,模拟价格计算
    public double computePrice(String productName) {

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }


}
  static List<Emall> list = Arrays.asList(
            new Emall("jdong"),
            new Emall("dangdang"),
            new Emall("taobao"),
            new Emall("pdd"),
            new Emall("tmall")
    );

    // 实现基本的功能需求
    //  List<Emall> --> map --> List<String>
    public static List<String> getPrice(List<Emall> list, String productName) {
        return list.stream().map(emall ->
                String.format(productName + " in %s price is %.2f",
                        emall.getEmallName(), emall.computePrice(productName))
        ).collect(Collectors.toList());
    }
  • 代码实现2(一口气查询):
  public static List<String> getPriceByCompletableFuture(List<Emall> list, String productName) {
        List<String> collect = list.stream().map(emall ->    // 将每个商城对象emall映射成一个CompletableFuture异步任务,即将每个emall放到异步任务的线程中
                        CompletableFuture.supplyAsync(() ->
                                String.format(productName + " in %s price is %.2f",
                                        emall.getEmallName(), emall.computePrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(s -> s.join())
                .collect(Collectors.toList());
        return collect;
    }
  • 两种实现方式的性能对比:
 public static void main(String[] args) {

        long startTime = System.currentTimeMillis();
        List<String> list2 = getPriceByCompletableFuture(list, "mysql");
        for (String element : list2) {
            System.out.println(element);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("异步处理任务 ----costTime: "+(endTime - startTime) +" 毫秒");

        long startTime2 = System.currentTimeMillis();
        List<String> ansList = getPrice(list, "mysql");
        for (String ele : ansList) {
            System.out.println(ele);
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("同步处理任务 ----costTime: "+(endTime2 - startTime2) +" 毫秒");
 }

输出结果:

 mysql in jdong price is 110.77
 mysql in dangdang price is 110.44
 mysql in taobao price is 109.06
 mysql in pdd price is 109.14
 mysql in tmall price is 109.60
 异步处理任务 ----costTime: 1220 毫秒
 mysql in jdong price is 110.81
 mysql in dangdang price is 110.86
 mysql in taobao price is 110.08
 mysql in pdd price is 109.36
 mysql in tmall price is 109.12
 同步处理任务 ----costTime: 5050 毫秒

7、CompletableFuture常用方法

7.1、获得结果和触发计算

// 不见不散
public T get()
    
// 过时不候
public T get(long timeout, TimeUnit unit)
    
// 没有计算完成的情况下,给我一个替代结果 
// 立即获取结果不阻塞 计算完,返回计算完成后的结果  没算完,返回设定的valueIfAbsent值
public T getNow(T valueIfAbsent)
//  和get方法功能类似,但join方法不需要抛出异常
public T join()
private static void testGetAndGetNow() {
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "111";
    });

   // try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
    // 注释掉如上的Sleep方法,getNow返回的结果是方法中设置的值"2222"
    //  不注释如上的sleep方法,getNow方法的结果是future返回的结果值"111"

    System.out.println(future.getNow("2222"));
}
System.out.println(CompletableFuture.supplyAsync(() -> "abc").thenApply(r -> r + "123").join());
// abc123

7.2、处理计算结果

  • thenApply方法: 计算结果存在依赖关系,这两个线程串行化,当前步骤有异常的话就停止执行
 public static void main(String[] args) {
       //  注意: 这里最好不要使用 ExecutorService service = Executors.newFixedThreadPool(3);的方式来创建线程池(见阿里开发手册)
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
                //new ThreadPoolExecutor.AbortPolicy()
                //new ThreadPoolExecutor.DiscardPolicy()
                //new ThreadPoolExecutor.DiscardOldestPolicy()
        );
        // 当一个线程依赖另一个线程时用 thenApply 方法来把这两个线程串行化,
        CompletableFuture.supplyAsync(()->{

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("异步任务操作步骤 111");
            return 1;
        },threadPool).thenApply(res ->{
            System.out.println("异步任务操作步骤 222");
            return res + 2;
        }).thenApply(res ->{
            System.out.println("异步任务操作步骤 333");
           // int i = 10 / 0;   // 异常情况:哪步出错就停在哪步
            return res + 3;
        }).whenComplete((result,err)->{
            if (err == null){
                System.out.println("异步任务处理正常,计算结果为:" + result);  // result = 1 + 2 + 3 = 6
            }
        }).exceptionally(e->{
            e.getStackTrace();
            System.out.println(e.getMessage());
            return 404;
        });

        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭,即主线程执行太快,导致异步任务无法执行,可以让主线程Sleep几秒
        // 除了sleep的方法,还可以使用线程池来处理,注意,最后一定关闭线程池 threadPool.shutdown(); 否则,程序会一直处于运行状态
        System.out.println(Thread.currentThread().getName() + "\t" + " --- 主线程先去忙其他任务");
        // try {
        //    TimeUnit.SECONDS.sleep(1);
        // } catch (InterruptedException e) {
        //    throw new RuntimeException(e);
        // }
        threadPool.shutdown();
    }
  • handle方法: 出现异常也可以继续执行,根据带的异常参数可以进一步处理
// 当一个线程依赖另一个线程时用 handle 方法来把这两个线程串行化,
   // 异常情况:有异常也可以往下一步走,handle会根据异常参数在最后抛出对应的异常
   CompletableFuture.supplyAsync(() -> {
       //暂停几秒钟线程
       try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
       System.out.println("111");
       return 1024;
   }).handle((f,e) -> {
      // int age = 10/0;
       System.out.println("222");
       return f + 1;
   }).handle((f,e) -> {
       System.out.println("333");
       return f + 1;
   }).whenCompleteAsync((res,e) -> {
       System.out.println("任务处理的结果为: "+res);
   }).exceptionally(e -> {
       e.printStackTrace();
       return null;
   });

   System.out.println("-----主线程结束, END");

   // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
   try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }

7.3、消费计算结果

  • thenRun:thenRun(Runnable runnable),任务A和B依次先后执行,并且B不需要A的结果
  • thenAccept:thenAccept(Consumer action),任务A和B依次先后执行,B需要A的结果任务A和B依次先后执行,B需要A的结果,但是任务B无返回值
  • thenApply:thenApply(Function fn),任务A和B依次先后执行**,B需要A的结果,同时任务B有返回值**
   CompletableFuture.supplyAsync(()->{
            return 1;
        }).thenApply(num ->{
            return num + 2;
        }).thenApply(num ->{
            return  num + 3;
        }).thenAccept(num -> System.out.println(num));

        System.out.println("--------------------");

        System.out.println(CompletableFuture.supplyAsync(()-> "the resultA of thenRun").thenRun(()->{
            System.out.println("thenRun,B不需要A的结果");
        }).join());
        System.out.println(CompletableFuture.supplyAsync(()-> "任务A和B依次先后执行,B需要A的结果,thenAccept").thenAccept(res -> System.out.println(res + ",任务B无返回值")).join());
        System.out.println(CompletableFuture.supplyAsync(()-> "任务A和B先后执行,B需要A的结果").thenApply(str -> str + " --> 任务B有返回值").join());
  • 线程池运行选择
    - 如果没有传入自定义的线程池,则使用默认线程池ForkJoinPool
    - 如果执行第一个任务,传入了一个自定义线程池,调用thenRun方法执行第二个任务时,则第二个任务和第一个任务共用一个线程池,调用thenRunAsync方法执行第二个任务时,则第一个任务使用的是传入的自定义线程池,第二个任务使用的是ForkJoinPool
    - 可能存在程序处理太快的情况,系统会优化切换原则,直接使用主线程处理

7.4、计算速度选用

applyToEither方法:任务谁执行快,就用谁(选用执行速度最快的任务 返回的结果作为最后的总结果)

 public <U> CompletableFuture<U> applyToEither(
        CompletionStage<? extends T> other, Function<? super T, U> fn)

使用实例:

CompletableFuture<String> planA = CompletableFuture.supplyAsync(() -> {
    System.out.println("A coming in...");
    try {
        TimeUnit.SECONDS.sleep(2);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return "planA";
});

CompletableFuture<String> planB = CompletableFuture.supplyAsync(() -> {
    System.out.println("B coming in...");
    try {
        TimeUnit.SECONDS.sleep(3);
        //  TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return "planB";
});
CompletableFuture<String> result = planA.applyToEither(planB, p -> {
    return p + " is winner!";  // 两个任务planA和planB,谁执行得更快,p就是对应的返回结果
});

// 补充:
// join()和get()方法类似,其不同在于使用get方法需要抛出异常 或 进行异常捕获,
//  join()则不需要抛出异常,也不用进行异常捕获,但出现异常时,会直接抛异常
System.out.println(Thread.currentThread().getName() + "\t" +result.join());

7.5、合并计算结果

  • 两个CompletionStage任务都完成后,最终能把两个任务的结果一起交给thenCombine来处理,
    先完成的任务需要等待其他分支任务完成,最后合并任务的计算结果
  • thenCombine:将两个异步任务的返回结果进行合并,再返回最后的结果值
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread().getName() + "\t --- 开始执行任务1...");
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return 20;
    });

    CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread().getName() + "\t -- 开始执行任务2..");

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return 30;
    });

    CompletableFuture<Integer> result = future1.thenCombine(future2, (x, y) -> {
        System.out.println("---> 合并两个任务的计算结果");
        return x * y;
    });
    System.out.println(result.join());
    //System.out.println(result.get());   // get方法需要抛出异常或进行异常捕获

参考资料:尚硅谷2022版JUC并发编程

【JAVA8】CompletableFuture使用详解 CompletableFuture!让你的代码免受阻塞之苦! 灵活的使用`CompletableFuture`可以让我们感受java8的异步编程之美! 阅读详情

相关推荐

Java8异步类CompletableFuture详解

JDK8引入了一个新的类CompletableFuture

CharlesYooSky的博客 2729

Java多线程之CompletableFuture

文章目录1 CompletableFuture1.1 简介1.2 创建CompletableFuture1.2.1 构造函数创建1.2.2 supplyAsync创建1.2.3 runAsync创建1.3 异步回调方法1.3.1 thenApply / thenAccept / thenRun互相依赖1.3.1.1 thenApply1.3.1.2 thenAccept / thenRun1.3.2 exceptionally有返回1.3.3 whenComplete无返回1.3.4 handle有返回1.

上善若泪 2万+

Java并发编程:CompletableFuture异常处理详解

通过上述实例,我们可以看到提供了灵活的异常处理机制,包括默认的异常处理、方法、以及handle()方法等。正确使用这些机制,可以大大提高并发程序的健壮性和可靠性。

m0_62153576的博客 895

CompletableFuture:让你的代码免受阻塞之苦

文章目录前言场景说明CompletableFuture使用CompletableFuture的创建:结果的获取:异常处理:同步方法Pick异步方法查询所有店铺某个商品价格为什么仍需要CompletableFuture其他API介绍whenComplete计算结果的处理提供了三个方法说明示例thenApply转换提供了三个方法说明示例thenAccept结果处理提供了三个方法说明示例thenCompose异步结果流水化提供了三个方法说明示例执行流程图thenCombine组合结果提供了三个方法说明示例执行..

yangxiaofei_java的博客 1958

libfacedetection 框架阅读及扩展经验

libfacedetection 框架源码解析与扩展心得1. libfacedetection 框架简介2. 源码解析2.1 facedetectcnn.h2.2 facedetectcnn.cpp2.3 facedetectcnn-model.cpp3. 其他层的扩展--depthwise convolution 前段时间因为工作需要,对libfacedetection框架做了些扩展,在阅读源...

weixin_42616332的博客 1500

CCSP考后复盘:那些刷题时感觉良好,考场却发懵的题目到底长什么样?

本文深入分析了CCSP考试中常见的题目陷阱和解题策略,揭示了刷题与实战的差距。通过解析换装题、双胞胎选项和场景题等典型题型,帮助考生掌握拆题技巧和思维模式转变,提升应对CCSP考试的能力。

weixin_30485379的博客 436

Java并发编程,CompletableFuture详解

CompletableFuture是Java8引入的一个强大工具,它扩展了Future接口,提供了更灵活的方式来组合异步任务,并且支持链式调用和函数式编程风格。CompletableFuture的设计目标是简化并发编程中的复杂性,使得开发者可以更容易地构建非阻塞、响应式的应用程序。

横竖撇折点 1410

头歌操作系统2.3系统调用命令ls执行的系统调用

设置版本0内核为分析对象。然后一直c直到虚拟机出现。然后一直c就是答案了。

m0_74128952的博客 1万+

Java并发编程之 CompletableFuture 详解

Runnable 是 Java 并发编程中用于描述的最基础接口,它只负责定义任务的执行逻辑,而不关心任务的执行结果、执行状态或异常返回。通过 Runnable,任务的“要做什么”和“由谁来执行”被解耦开来,Runnable 只描述业务逻辑,而线程或线程池负责调度和执行。由于 Runnable 不提供返回值,也不具备结果管理能力,它更适合用于只关注执行过程、不关心执行结果的异步或并发场景。

qq_53324833的博客 1011

UE5 Compute Shader实战:从基础到高级应用全解析

本文全面解析了在UE5中应用Compute Shader的完整流程,从基础概念、环境搭建到核心机制与实战应用。详细介绍了如何通过参数传递、线程派遣与数据读写实现GPU并行计算,并深入探讨了GPU粒子模拟、性能优化及结合光线追踪等高级应用场景,为开发者掌握UE5高性能计算提供系统指导。

yhn45678901的博客 499

DroidGuard虚拟机逆向解析:指令集、密钥派生与反调试机制

DroidGuard是Google在Android生态中部署的轻量级定制虚拟机,用于设备完整性校验。其核心原理是通过自解释字节码、多层混淆指令集与动态密钥派生机制,在ART运行时构建静默安全沙箱。技术价值在于规避传统API检测盲区,实现高鲁棒性环境感知;典型应用场景包括金融SDK风控、Play Services可信启动及合规性审计。本文深入拆解其4字节指令编码规则、基于设备指纹的三阶段密钥派生(SHA256→Feistel→AES)、以及五层反调试体系(ptrace快照、时间差分、内存页探测、指令流校验、服

weixin_32736961的博客 586

Java并发编程——CompletableFuture详解

Future/Callable Java 1.5开始,提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。 Future接口可以构建异步应用,是多线程开发中常见的设计模式。 当我们需要调用一个函数方法时。如果这个函数执行很慢,那么我们就要进行等待。但有时候,我们可能并不急着要结果。 因此,我们可以让被调用者立即返回,让他在后台慢慢处理这个请求。对于调用者来说,则可以先处理一些其他任务,在真正需要数据的场合再去尝试获取需要的数据。 简单实现 public class Fut

Java是世界上最好的语言 3024

PX4固件下VTOL固定翼的3种起飞方式对比:手抛vs弹射vs跑道

本文深度解析PX4固件下VTOL固定翼的三种起飞方式:手抛、弹射与跑道起飞,对比其技术差异与适用场景。通过详细的参数配置和工程实践指南,帮助开发者优化起飞性能,提升无人机在不同环境下的适应性和可靠性。文章特别针对PX4飞控系统的最新特性进行了技术探讨。

weixin_30296405的博客 87

Java并发编程中的CompletableFuture详解与实践

Java并发编程中的CompletableFuture详解与实践

weixin_43580435的博客 375

大语言模型与ROS集成的自然语言机器人控制:开源框架与应用实例

近年来,大语言模型(LLM)与机器人操作系统(ROS)的集成逐步成熟,使得自然语言驱动的机器人控制成为可能。用户输入“捡起绿色方块”或“把微波炉里的饭热好端过来”这类日常语句,机器人能够自动拆解步骤、规划动作并执行。本文梳理2026年前后发布的三个代表性开源框架——ROS-LLM、ROSClaw以及LLM+Nav2基准测试系统,介绍其技术路径与工程落地情况。

Studying…… 633

基于深度学习的生活垃圾检测与分类系统:YOLOv5、YOLOv6、YOLOv7与YOLOv8实现

本项目的目标是开发一个基于YOLO系列模型的生活垃圾检测与分类系统。数据集准备与标注:收集并标注生活垃圾图像数据集。模型训练:使用YOLOv5、YOLOv6、YOLOv7、YOLOv8等深度学习模型训练垃圾分类系统。UI界面设计:设计一个简洁的用户界面,支持图像或视频的上传与垃圾分类结果展示。实时垃圾检测与分类:通过摄像头进行实时垃圾检测和分类。结果展示与保存:展示检测结果,支持用户保存分类后的图像或视频。

YOLO 705

CompletableFuture详解、什么是CompletableFuture类,怎么在java并发编程、多线程中使用(结合案例,保姆级教程))

java并发编程、多线程、CompletableFuture

zhangfuping123456789的博客 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Java并发编程第7讲——CompletableFuture、Future和ForkJoinPool(万字详解)

CompletableFuture是Java 8中引入的一个类,用于异步编程和并发操作,它大约提供了50个不同的方法,用于组合、合并和执行异步计算步骤以及处理错误。CompletableFuture类实现了Future和CompletionStage接口,这两个接口分别代表了异步任务的结果和完成状态,以及异步任务之间的依赖关系。

让~学习~成为一种习惯(橡 皮 人の技术博客) 4665

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

并发编程系列 - Java线程池监控及CompletableFuture详解

目录Java线程池核心原理与最佳实践前言Java中的线程池功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 Java线程池核心原理与最佳实践 前言 Java后端开发中我们经常使用线程池( ThreadPool )去提升程序的性能。通

知行 6079

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Java「并发编程」Future模式(内有CompletableFuture的详解)

斯蒂芬朱cPlusPlus2019-05-23 09:13:00 Future Future是Java5增加的类,它用来描述一个异步计算的结果。你可以使用 isDone 方法检查计算是否完成,或者使用 get 方法阻塞住调用线程,直到计算完成返回结果。你也可以使用 cancel 方法停止任务的执行。下面来一个栗子: public class FutureDemo { public st...

u011277123的博客 1797

Java并发编程实战CompletableFuture异步任务处理技巧详解

CompletableFuture是Java并发工具箱中一个极其强大的组件,它将异步编程从简单的“提交并等待”提升到了“组装与响应”的新高度。通过熟练掌握其链式组合、结果聚合和异常处理机制,开发者可以构建出高效、清晰且易于维护的异步应用程序。理解其底层原理并结合最佳实践(如合理的线程池使用和超时控制),是充分发挥其潜力的关键。随着项目复杂度的增加,CompletableFuture与其他响应式编程库(如Project Reactor)的协同使用,将成为处理高并发系统的有力武器。

nichlas_yu的专栏 425

【Java并发编程】Future 与 CompletableFuture 实战详解(高并发推荐)

本文系统讲解了 Java 并发编程中两个重要的异步工具 —— Future 和 CompletableFuture。从基本用法、核心方法、优缺点对比,到实际代码示例与性能测试,全面展示它们在异步任务处理、任务组合、异常链路管理等方面的应用场景与差异。特别是对 CompletableFuture 的链式调用、组合处理、异常补偿等强大功能进行了深入剖析,适合中高级 Java 工程师快速掌握现代并发工具的实战技巧。

七一 871

java并发编程(7):CompletableFuture异步框架源码详解及实例

CompletableFuture为异步编程框架,当我们在使用线程池处理任务时,我们只能通过阻塞的Future#get()获取异步的结果,当任务处理需要的时间比较长时,效率和性能就会比较差。而CompletableFuture弥补了Future,其主要是在任务处理完成后,调用应用的回调函数,这样应用就无需通过Future#get()的方式获取处理结果,而是通过任务的回调来通知应用结...

yuanwei1144的博客 388

【Java并发编程实战】CompletableFuture 核心功能使用场景详解

这些示例展示了 CompletableFuture 的核心功能,可以根据具体需求组合使用。默认线程池(ForkJoinPool)

gaochufukanyongren的博客 42

java 异步框架,java并发编程(7):CompletableFuture异步框架源码详解及实例

CompletableFuture为异步编程框架,当我们在使用线程池处理任务时,我们只能通过阻塞的Future#get()获取异步的结果,当任务处理需要的时间比较长时,效率和性能就会比较差。而CompletableFuture弥补了Future,其主要是在任务处理完成后,调用应用的回调函数,这样应用就无需通过Future#get()的方式获取处理结果,而是通过任务的回调来通知应用结果,这样极大的提...

weixin_31437695的博客 617

Java并发编程 - 异步回调:Futrue 的实现类CompletableFuture

是一个非常强大的工具,它使得异步编程变得更加容易和直观。通过使用,你可以轻松地处理异步操作、组合多个异步操作的结果,并优雅地处理异常。在编写高性能和响应式的Java应用程序时,是一个不可或缺的工具。

qq_33240556的博客 518
上一篇: 图文并茂,一文带你掌握RabbitMQ
下一篇: JavaSE基础回顾之反射知识点以及面试总结
咸鱼也有爱
博客等级 码龄7年 133粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值