CompletableFuture+线程池使用案列

案例一

java 复制代码
@RestController
@RequestMapping("/export")
public class ExportController {

    private final ExecutorService executor = Executors.newFixedThreadPool(5);

    @GetMapping("/multiSheet")
    public void exportMultiSheet(HttpServletResponse response) throws Exception {
        // 构造5个CompletableFuture,每个处理自己的表和业务逻辑
        CompletableFuture<SheetData> future1 = CompletableFuture.supplyAsync(() -> handleUsers(), executor);
        CompletableFuture<SheetData> future2 = CompletableFuture.supplyAsync(() -> handleOrders(), executor);
        CompletableFuture<SheetData> future3 = CompletableFuture.supplyAsync(() -> handleProducts(), executor);
        CompletableFuture<SheetData> future4 = CompletableFuture.supplyAsync(() -> handleLogs(), executor);
        CompletableFuture<SheetData> future5 = CompletableFuture.supplyAsync(() -> handleCustomers(), executor);

        // 等待所有处理完成
        CompletableFuture<Void> allDone = CompletableFuture.allOf(future1, future2, future3, future4, future5);

        allDone.thenRun(() -> {
            try {
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                String fileName = URLEncoder.encode("multi_sheet_export", "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

                ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

                // 依次写入每个Sheet(join获取数据)
                List<CompletableFuture<SheetData>> futures = Arrays.asList(future1, future2, future3, future4, future5);

                for (int i = 0; i < futures.size(); i++) {
                    SheetData data = futures.get(i).join();
                    WriteSheet sheet = EasyExcel.writerSheet(i, data.getSheetName())
                            .head(data.getHead())
                            .build();
                    excelWriter.write(data.getRows(), sheet);
                }

                excelWriter.finish();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                executor.shutdown(); // 一定要关闭线程池
            }
        }).join(); // 等待导出完成
    }

    // 示例方法,每个表处理逻辑不同
    private SheetData handleUsers() {
        // 查询 users 表,并处理逻辑(脱敏、计算、筛选等)
        return queryAndBuildSheet("users", "用户信息");
    }

    private SheetData handleOrders() {
        // 查询 orders 表,自定义业务逻辑处理
        return queryAndBuildSheet("orders", "订单信息");
    }

    private SheetData handleProducts() {
        return queryAndBuildSheet("products", "商品列表");
    }

    private SheetData handleLogs() {
        return queryAndBuildSheet("logs", "操作日志");
    }

    private SheetData handleCustomers() {
        return queryAndBuildSheet("customers", "客户信息");
    }

    // 通用方法:查询数据库并生成 SheetData
    private SheetData queryAndBuildSheet(String tableName, String sheetName) {
        List<List<String>> headers = new ArrayList<>();
        List<List<String>> rows = new ArrayList<>();

        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/your_db", "user", "password");
             PreparedStatement stmt = conn.prepareStatement("SELECT * FROM " + tableName);
             ResultSet rs = stmt.executeQuery()) {

            ResultSetMetaData meta = rs.getMetaData();
            int columnCount = meta.getColumnCount();

            List<String> headerRow = new ArrayList<>();
            for (int i = 1; i <= columnCount; i++) {
                headerRow.add(meta.getColumnLabel(i));
            }
            headers.add(headerRow);

            while (rs.next()) {
                List<String> row = new ArrayList<>();
                for (int i = 1; i <= columnCount; i++) {
                    Object val = rs.getObject(i);
                    // 可以在这里做字段处理,比如脱敏、格式转换等
                    row.add(val != null ? val.toString() : "");
                }
                rows.add(row);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return new SheetData(sheetName, headers, rows);
    }

    // SheetData结构,用于封装每个 Sheet 页的数据
    static class SheetData {
        private final String sheetName;
        private final List<List<String>> head;
        private final List<List<String>> rows;

        public SheetData(String sheetName, List<List<String>> head, List<List<String>> rows) {
            this.sheetName = sheetName;
            this.head = head;
            this.rows = rows;
        }

        public String getSheetName() { return sheetName; }

        public List<List<String>> getHead() { return head; }

        public List<List<String>> getRows() { return rows; }
    }
}

案例二

java 复制代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
public class ExportController {

    private final UserService userService;
    private final OrderService orderService;
    private final ProductService productService;
    private final CustomerService customerService;
    private final InvoiceService invoiceService;

    public ExportController(UserService userService,
                            OrderService orderService,
                            ProductService productService,
                            CustomerService customerService,
                            InvoiceService invoiceService) {
        this.userService = userService;
        this.orderService = orderService;
        this.productService = productService;
        this.customerService = customerService;
        this.invoiceService = invoiceService;
    }

    @GetMapping("/export")
    public void exportExcel(HttpServletResponse response) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        try {
            CompletableFuture<List<User>> userFuture = CompletableFuture.supplyAsync(userService::list, executor);
            CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(orderService::list, executor);
            CompletableFuture<List<Product>> productFuture = CompletableFuture.supplyAsync(productService::list, executor);
            CompletableFuture<List<Customer>> customerFuture = CompletableFuture.supplyAsync(customerService::list, executor);
            CompletableFuture<List<Invoice>> invoiceFuture = CompletableFuture.supplyAsync(invoiceService::list, executor);

            CompletableFuture<Void> all = CompletableFuture.allOf(userFuture, orderFuture, productFuture, customerFuture, invoiceFuture);
            all.join(); // 等待全部完成

            List<User> users = userFuture.join();
            List<Order> orders = orderFuture.join();
            List<Product> products = productFuture.join();
            List<Customer> customers = customerFuture.join();
            List<Invoice> invoices = invoiceFuture.join();

            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("数据导出", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 写入多个 sheet
            ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build();

            writer.write(users, EasyExcel.writerSheet(0, "用户").head(User.class).build());
            writer.write(orders, EasyExcel.writerSheet(1, "订单").head(Order.class).build());
            writer.write(products, EasyExcel.writerSheet(2, "产品").head(Product.class).build());
            writer.write(customers, EasyExcel.writerSheet(3, "客户").head(Customer.class).build());
            writer.write(invoices, EasyExcel.writerSheet(4, "发票").head(Invoice.class).build());

            writer.finish();
        } finally {
            executor.shutdown();
        }
    }
}

// 假设以下是实体类,省略 Getter/Setter
class User { private Long id; private String name; }
class Order { private Long id; private String number; }
class Product { private Long id; private String title; }
class Customer { private Long id; private String name; }
class Invoice { private Long id; private String invoiceNo; }

// 假设以下是 Service 接口
interface UserService { List<User> list(); }
interface OrderService { List<Order> list(); }
interface ProductService { List<Product> list(); }
interface CustomerService { List<Customer> list(); }
interface InvoiceService { List<Invoice> list(); }
相关推荐
坐吃山猪4 小时前
SpringBoot01-配置文件
java·开发语言
我叫汪枫4 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao5 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区6 小时前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT7 小时前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy7 小时前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss8 小时前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续9 小时前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben0449 小时前
ReAct模式解读
java·ai