Java异步CompletableFuture

本文深入探讨了Java中CompletableFuture的使用方法,包括异步回调、异常处理、任务组合等高级特性,通过实例展示了如何有效提升应用的并发性能。
package integral;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 
 * @author YangTG
 * 异步执行
 */
public class CompletableFutureDemo {
	
	public static void any(){
		System.out.println("runAsync..");
	}
	
	public static String any1(){
		return "supplyAsync...";
	}
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		
		List<CompletableFuture> list = new ArrayList<>();
		int i=0;
		//没有返回值异步
		/*while(i<5){
			CompletableFuture<Void> comp = new CompletableFuture<>().runAsync(()->{
				CompletableFutureDemo.any();
				
			});
			list.add(comp);
			i++;
		}*/
		CompletableFuture<String> future =null;
		//有返回值
		while(i<5){
			 future = new CompletableFuture<>().supplyAsync(()->{
				return CompletableFutureDemo.any1();
			});
			list.add(future);
			i++;
		}
		//之前执行
		future.thenRun(()->{
			CompletableFutureDemo.any();
		});
		System.out.println("执行完毕");
		list.forEach(a->{
			try {
				System.out.println(a.get());
			} catch (Exception e) {
				e.printStackTrace();
			} 
		});
	}
}

执行结果

runAsync..
执行完毕
supplyAsync...
supplyAsync...
supplyAsync...
supplyAsync...
supplyAsync...
package CompletableFuture;

import java.util.concurrent.CompletableFuture;

public class Demo {

    public static void main(String[] args) throws Exception {
        //demo1();
        //demo2();
        //demo3();
        //demo4();
        //demo5();
        demo6();
    }

    /**
     * 异步回调 没有返回值
     *
     * @throws Exception
     */
    public static void demo1() throws Exception {
        // 创建异步返回任务
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });
        //创建不带返回值异步任务 cf2,该任务的需要cf的结果作为异步任务的参数
        CompletableFuture<Void> cf2 = cf.thenAcceptAsync(result -> {
            String s = result + " thenAcceptAsync";
            System.out.println(s);
        });
        cf2.get();
        CompletableFuture<Void> cf3 = cf.thenAccept(result -> {
            String s = result + " thenAccept";
            System.out.println(s);
        });
        cf3.get();
    }

    /**
     * 异步回调 有返回值
     *
     * @throws Exception
     */
    public static void demo2() throws Exception {
        // 创建异步返回任务
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });
        //创建带返回值异步任务 cf2,该任务的需要cf的结果作为异步任务的参数
        CompletableFuture<String> cf2 = cf.thenApply(result -> {
            String s = result + " thenApply";
            return s;
        });
        System.out.println(cf2.get());
        CompletableFuture<String> cf3 = cf.thenApplyAsync(result -> {
            return result + " thenApplyAsync";
        });
        System.out.println(cf3.get());
    }

    /**
     * 异常回调
     *
     * @throws Exception
     */
    public static void demo3() throws Exception {
        // 创建异步返回任务
        CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
            Integer[] integers = new Integer[3];
            return integers[5];
        });
        //cf 发生异常后执行该方法,返回cf2结果
        // 如果没有发生异常不执行,并且返回cf的结果值
        CompletableFuture<Integer> cf2 = cf.exceptionally(e -> {
            System.out.println("cf exception " + e.getMessage());
            return 3;
        });
        System.out.println(cf2.get());
    }

    /**
     * 当某个任务执行完成后回调的方法,没有返回值
     *
     * @throws Exception
     */
    public static void demo4() throws Exception {
        // 创建异步返回任务
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });
        // cf执行完成后会将执行结果与执行异常传染源回调方法 cf2
        CompletableFuture<String> cf2 = cf.whenComplete((a, e) -> {
            System.out.println("a:" + a);
            System.out.println("b:" + e.getMessage());
        });
        System.out.println(cf2.get());
    }

    /**
     * 当某个任务执行完成后回调的方法,有返回值
     *
     * @throws Exception
     */
    public static void demo5() throws Exception {
        // 创建异步返回任务
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });
        // cf执行完成后会将执行结果与执行异常传染源回调方法 cf2
        // 参数 a 是cf的返回值,参数 e 是cf的异常
        CompletableFuture<String> cf2 = cf.handle((a, e) -> {
            System.out.println("a:" + a);
            System.out.println("b:" + e.getMessage());
            return " handle";
        });
        System.out.println(cf2.get());
    }

    /**
     * allOf / anyOf
     * 多个任务执行完成后才会执行
     *
     * @throws Exception
     */
    public static void demo6() throws Exception {
        // 创建异步返回任务
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });

        // 创建异步返回任务
        CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {
            return "word";
        });
        // allOf 所有任务执行完成后才会执行cf3.如果有一个任务异常中止,则cf3会抛出异常。如果全部正常执行,cf3会返回null
        CompletableFuture<Void> cf3 = CompletableFuture.allOf(cf, cf2).thenApply(result -> {
            return result;
        });
        System.out.println("cf3 " + cf3.get());

        //anyOf只要有一个任务执行完成,无论是正常执行还是执行异常,cf4的result都是已经执行完成任务的的结果
        CompletableFuture<Object> cf4 = CompletableFuture.anyOf(cf, cf2).thenApply(result -> {
            return result;
        });
        System.out.println("cf4:" + cf4.get());
    }
}

<think>好的,我现在需要帮助用户理解如何使用Java中的CompletableFuture实现异步导出。根据用户提供的引用内容,特别是引用[4]提到的使用CompletableFuture处理耗时任务,比如数据表格导出,结合其他引用中的方法,我需要整理出一个清晰的步骤和示例。 首先,用户的需求是导出数据时,可能涉及多个耗时查询,这些查询可以并行执行,然后等待所有结果再进行后续处理。这正好可以用CompletableFuture异步特性来实现。引用[1]和[2]提到thenApply和链式调用,而引用[3]提到了组合多个任务的方法,如allOf和anyOf。引用[4]则具体提到了在导出场景中的应用。 接下来,我需要确定实现步骤。通常,导出流程可能包括:用户触发导出,创建异步任务,并行执行数据查询,组装数据,生成文件,通知用户下载。根据引用[5],可能还需要结合WebSocket通知前端。 然后,考虑代码示例。需要展示如何创建CompletableFuture,使用supplyAsync执行异步任务,使用thenApply处理结果,以及使用allOf等待所有任务完成。例如,用户可能需要查询订单、用户和商品数据,这些可以并行处理,然后合并数据生成Excel。 需要注意异常处理,比如使用exceptionally方法。同时,要展示如何获取所有结果,使用join或get。引用[3]中的acceptEither可能不适用,因为需要所有任务完成,所以应该用allOf。 最后,生成相关问题,帮助用户深入理解,如性能优化、异常处理、与其他工具结合等。</think>### 如何使用Java CompletableFuture实现异步导出 #### 一、实现思路 1. **用户触发导出**:前端发起导出请求,后端创建异步任务 2. **并行执行耗时查询**:使用`CompletableFuture.supplyAsync()`并行执行多个数据查询 3. **同步等待结果**:通过`CompletableFuture.allOf()`等待所有任务完成 4. **数据组装处理**:使用`.thenApply()`进行结果合并与数据处理 5. **文件生成与通知**:生成文件后通过WebSocket通知前端下载[^5] #### 二、完整代码示例 ```java public class ExportService { // 模拟数据查询服务 private OrderService orderService; private UserService userService; private ProductService productService; public CompletableFuture<String> asyncExport(Long taskId) { // 1. 创建异步任务 CompletableFuture<List<Order>> futureOrders = CompletableFuture.supplyAsync( () -> orderService.queryOrders(), Executors.newCachedThreadPool() ).exceptionally(ex -> { System.err.println("订单查询失败: " + ex.getMessage()); return Collections.emptyList(); }); CompletableFuture<List<User>> futureUsers = CompletableFuture.supplyAsync( () -> userService.queryUsers() ); CompletableFuture<List<Product>> futureProducts = CompletableFuture.supplyAsync( () -> productService.queryProducts() ); // 2. 等待所有任务完成并处理结果 return CompletableFuture.allOf(futureOrders, futureUsers, futureProducts) .thenApply(v -> { try { List<Order> orders = futureOrders.get(); List<User> users = futureUsers.get(); List<Product> products = futureProducts.get(); // 3. 数据组装 ExportData exportData = assembleData(orders, users, products); // 4. 生成Excel文件 String filePath = generateExcel(exportData); return filePath; } catch (InterruptedException | ExecutionException e) { throw new RuntimeException("数据组装失败", e); } }); } private String generateExcel(ExportData data) { // 实现Excel生成逻辑 return "/export/files/report_2023.xlsx"; } } ``` #### 三、关键API说明 1. **`supplyAsync()`**:创建异步任务并返回`CompletableFuture` ```java CompletableFuture.supplyAsync(() -> {...}, executor) ``` 2. **`allOf()`**:等待所有任务完成 ```java CompletableFuture.allOf(future1, future2) .thenApply(v -> {...}) ``` 3. **`thenApply()`**:链式处理结果 ```java future.thenApply(data -> transform(data)) ``` 4. **`exceptionally()`**:异常处理 ```java future.exceptionally(ex -> handleError(ex)) ``` #### 四、WebSocket通知集成示例 ```java @Async public void handleExportTask(Long taskId) { CompletableFuture<String> exportFuture = asyncExport(taskId); exportFuture.thenAccept(filePath -> { // 通过WebSocket通知前端 websocketSender.send(taskId, "EXPORT_SUCCESS", filePath); }).exceptionally(ex -> { websocketSender.send(taskId, "EXPORT_FAILED", ex.getMessage()); return null; }); } ``` #### 五、最佳实践建议 1. **线程池配置**:建议使用自定义线程池控制并发量 ```java ExecutorService executor = Executors.newFixedThreadPool(10); ``` 2. **超时控制**:添加超时机制避免长时间阻塞 ```java future.get(30, TimeUnit.SECONDS); ``` 3. **结果缓存**:对已完成的导出任务进行缓存[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值