首页 > 编程语言 >Java8 CompletableFuture异步任务

Java8 CompletableFuture异步任务

时间:2024-11-14 15:59:56浏览次数:1  
标签:异步 Java8 util future CompletableFuture import 返回值 public

无返回值调用

import java.util.concurrent.CompletableFuture;
 
public class TestDemo {
 
    public static void main(String[] args) {
        System.out.println("进入主线程=============");
        CompletableFuture.runAsync(()->getNum());
        System.out.println("主线程结束=============");
    }
	
	public void getNum(){
		System.out.println("执行线程=============");
	}
}

有返回值调用

import java.util.concurrent.CompletableFuture;
 
public class TestDemo {
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
		// 无返回值 runAsync() 有返回值 supplyAsync()
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> getNum());
        System.out.println(future.get());
    }

    private static Integer getNum() {
        return 5 / 2;
    }
}

使用自定义线程池

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class TestDemo {
    /**
     * 自定义线程池
     */
    public static ExecutorService service = Executors.newFixedThreadPool(5);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
		// 无返回值 runAsync() 有返回值 supplyAsync()
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> getNum(),service);
        System.out.println(future.get());
    }

    private static Integer getNum() {
        return 5 / 2;
    }
}

处理异常

handleAsync
该方法有两个参数,一种一个是上一步的结果,另一个则是上一步的异常。而且如果出现异常则第一个参数为null,如果没有异常则第二个参数为null。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class TestDemo {
    /**
     * 自定义线程池
     */
    public static ExecutorService service = Executors.newFixedThreadPool(5);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
		// 无返回值 runAsync() 有返回值 supplyAsync()
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> getNum(),service).handleAsync((res, e) -> {
            if (res != null) {
                return res;
            }
            if (e != null) {
                return 0;
            }
            return 0;
        });
        System.out.println(future.get());
    }

    private static Integer getNum() {
	    // by zero 
        return 5 / 0;
    }
}

也可以使用 exceptionally 对异常进行单独处理。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class TestDemo {
    /**
     * 自定义线程池
     */
    public static ExecutorService service = Executors.newFixedThreadPool(5);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
		// 无返回值 runAsync() 有返回值 supplyAsync()
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> getNum(),service).exceptionally((e) -> {
            System.out.println(e.getMessage());
            return 0;
        });
        System.out.println(future.get());
    }

    private static Integer getNum() {
	    // by zero 
        return 5 / 0;
    }
}

多任务组合

使用CompletableFuture主要就是为了完成异步任务的编排。所以第三步也是我们最重要的应用。常见的多个任务组合会有以下几种情况

  • 1.业务二会用到业务一的结果

针对第一种情况,这个直接使用上一步handle直接对结果进行处理就好。相对比较简单。

  • 2.业务三需要等到业务一和业务二都完成

定义:
业务一 future
业务一 返回值f1

业务二 future2
业务二 返回值f2

如果不需要接收业务一和业务二的返回值,并且自己也不用返回值那么就可以使用:future.runAfterBothAsync(future2,() ->{});

如果需要使用业务一和业务二的返回值,但是在业务三不需要返回值那么可以使用:future.thenAcceptBothAsync(future2,(f1,f2) ->{},service);

如果需要使用业务一和业务二的返回值,并且自己也需要有返回值则使用:future.thenCombineAsync(future2, (f1, f2) -> { return f1 + f2; }, service);

  • 3.业务三需要等到业务一或者业务二其中之一完成

定义:
业务一 future
业务一 返回值f1

业务二 future2
业务二 返回值f2

如果不需要接收业务一或者业务二的返回值,并且自己也不用返回值那么就可以使用:future.runAfterEitherAsync(future2,()->{});

如果需要使用业务一或者业务二的返回值,但是在业务三不需要返回值那么可以使用:future.acceptEitherAsync(future2,(f)->{});

如果需要使用业务一或者业务二的返回值,并且自己也需要有返回值则使用:future.applyToEitherAsync(future2,(f)->{return 0;});

具体情况可以根据下面的代码修改测试:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class CompletableFutureTest {
 
    public static ExecutorService service = Executors.newFixedThreadPool(5);
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("进入主线程============= ");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            int k = 10 / 2;
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("计算结果k = " + k);
            return k;
        },service);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            int k = 10 * 2;
            System.out.println("计算结果k2 = " + k);
            return k;
        },service);
        CompletableFuture<Integer> combineAsync = future.thenCombineAsync(future2, (f1, f2) -> {
            System.out.println("最终执行任务3:" + f1 + "===========" + f2);
            return f1 + f2;
        }, service);
        Integer integer = combineAsync.get();
        System.out.println("integer = " + integer);
        System.out.println("主线程结束============= ");
    }
}

补充:此外还有allOf 和anyOff ,这两个方法可以传入多个任务。同理,allOf是等待所有任务都完成了,anyOf是有任意一个任务完成即可。

标签:异步,Java8,util,future,CompletableFuture,import,返回值,public
From: https://www.cnblogs.com/1399z3blog/p/18546195

相关文章

  • Java8
    Lambda一、简介Lambda表达式是Java8引入的一种新的语法,它允许你以简洁的方式表示可传递给方法或存储在变量中的代码块。Lambda表达式可以用来替代匿名内部类,使代码更加简洁、易读和易于维护。二、Lambda表达式的基本语法Lambda表达式的语法形式为:(parameters)->expre......
  • 深入理解Spring框架中的@Async注解实现异步任务
    目录1.引言2.环境准备3.启用异步支持4.创建异步任务5.调用异步任务6.运行应用7.使用@Async需要注意的地方8.结论在现代Web应用中,异步任务的执行变得越来越重要。Spring框架提供了强大的@Async注解,可以帮助开发者轻松实现异步任务。本文将详细介绍如何在Sprin......
  • 同步异步,阻塞非阻塞
    同步异步,阻塞非阻塞区别: 同步:调用者发出请求后,一直等待被调用者返回结果或通知,才进行下一步操作。 异步:调用者发出请求后,不等待被调用者返回结果或通知,就进行下一步操作。阻塞:调用者发出请求后,被调用者不返回结果或通知,调用者就一直等待,不能进行其他操作。 非阻塞:调用者发出请......
  • 【Nginx学习】深入 Nginx:4大步骤揭秘 Nginx 请求的多阶段异步处理
    ......
  • Vue功能菜单的异步加载、动态渲染
            实际的Vue应用中,常常需要提供功能菜单,例如:文件下载、用户注册、数据采集、信息查询等等。每个功能菜单项,对应某个.vue组件。下面的代码,提供了一种独特的异步加载、动态渲染功能菜单的构建方法:<scriptsetup>import{defineComponent,getCurrentInstance,h}......
  • 异步电动机的直接转矩控制系统
    异步电动机的直接转矩控制系统(DTC)是一种高性能的交流电机调速技术,通过直接控制电机的瞬时电压来控制电机定子磁链的瞬时旋转速度。以下是对异步电动机的直接转矩控制系统的详细介绍:基本原理基本思想:直接转矩控制的基本思想是根据定子磁链幅值偏差和电磁转矩偏差的正负符号,再......
  • RMQ异步通信处理机制
                          场景再现    在一个微服务架构的商城系统中有两个服务:下单服务和库存服务。当我们进行下单的时候,此时会调用库存服务,进行库存的扣减。这种服务间的调用/通信我们之前是用FeignClient以接口式的请求......
  • Vue3 - 详细实现虚拟列表前端虚拟滚动列表解决方案,vue3长列表优化之虚拟列表,解决列表
    前言Vue2版本,请访问这篇文章在vue3项目开发中,详解实现虚拟列表高度不固定(不定高)且复杂含有图片视频等复杂虚拟列表教程,决列表每项高度不确定及img图像或视频的加载方案,利用缓冲区技术解决用户浏览时渲染不及时列表闪烁白屏/列表加载闪屏,解vue3实现虚拟列表优化大......
  • 深入解析 WKWebView 的 didFinish 回调时机:页面加载与异步操作的处理
    在iOS开发中,我们经常会用WKWebView来加载和展示H5页面。通常,开发者会在WKWebView的didFinish方法中处理页面加载完成后的逻辑,例如更新UI或执行后续操作。然而,didFinish的触发时机并不总是如我们所期待,它并不会等待所有异步操作(如AJAX请求、图片加载等)完成后再执行......
  • es6,for....of是异步的嘛? 如何实现循环中异步实现
    for...of循环本身不是异步的,它是同步执行的。这意味着for...of循环会按顺序依次执行每一项,直到循环结束。如果循环中的操作是异步的(例如,async函数或者Promise),则这些异步操作会并发执行,但for...of本身不会等待这些操作完成,除非你显式地处理它们。让我们通过一个例子来说明......