用java写一个多线程异步批量入库

本文介绍了如何使用Java通过ExecutorService和线程池实现异步批量入库,模拟了数据生成和按批次提交任务的过程,展示了并发处理大量数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面是一个用 Java 实现的多线程异步批量入库的示例:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BatchInsertDemo {

    private static final int BATCH_SIZE = 1000;  // 每批次入库的数据量
    private static final int THREAD_POOL_SIZE = 5;  // 线程池大小
    private static final int TOTAL_COUNT = 10000;  // 总共需要入库的数据量

    public static void main(String[] args) {

        // 模拟数据
        List<Data> dataList = new ArrayList<>();
        for (int i = 1; i <= TOTAL_COUNT; i++) {
            dataList.add(new Data(i));
        }

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

        // 按批次提交任务
        int start = 0;
        while (start < TOTAL_COUNT) {
            int end = Math.min(start + BATCH_SIZE, TOTAL_COUNT);
            List<Data> batchList = dataList.subList(start, end);
            BatchInsertTask task = new BatchInsertTask(batchList);
            executorService.submit(task);
            start = end;
        }

        // 关闭线程池
        executorService.shutdown();
    }

    // 数据对象
    private static class Data {
        private int id;
        public Data(int id) {
            this.id = id;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    }

    // 入库任务
    private static class BatchInsertTask implements Runnable {

        private List<Data> dataList;

        public BatchInsertTask(List<Data> dataList) {
            this.dataList = dataList;
        }

        @Override
        public void run() {
            // 执行批量入库逻辑
            System.out.printf("开始入库,当前批次共有 %d 条数据\n", dataList.size());
            try {
                Thread.sleep(1000);  // 模拟入库耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("完成入库,当前批次共有 %d 条数据\n", dataList.size

### Java多线程编程实战案例与应用 #### 生产者消费者模型 生产者消费者问题是经典的多线程同步问题之一,在Java中可以通过`BlockingQueue`接口来实现。该接口提供了阻塞队列,能够很好地解决生产和消费之间的协调问题。 ```java import java.util.concurrent.*; class Producer implements Runnable { private final BlockingQueue<Integer> queue; public Producer(BlockingQueue<Integer> q) { this.queue = q; } @Override public void run() { try { while (true) { Integer item = produce(); System.out.println(Thread.currentThread().getName()+" produced "+item); queue.put(item); // 如果队满则等待直到有空间可用 Thread.sleep((long)(Math.random()*100)); } } catch (InterruptedException e) {} } private int produce() throws InterruptedException{ return new Random().nextInt(100)+1; } } class Consumer implements Runnable { private final BlockingQueue<Integer> queue; public Consumer(BlockingQueue<Integer> q) {this.queue=q;} @Override public void run(){ try{ while(true){ Integer consumedItem=queue.take(); // 若为空,则一直等到有数据为止 System.out.println(Thread.currentThread().getName()+" consumed "+consumedItem); consume(consumedItem); Thread.sleep((long)(Math.random()*100)); } }catch(InterruptedException ex){} } private void consume(Integer i){ /* ... */ } } ``` 上述代码展示了如何利用`BlockingQueue`构建简单的生产者-消费者模式[^1]。 #### 文件下载器 另一个常见的应用场景是在网络应用程序中的文件下载功能。当用户请求下载大型文件时,可以启动多个子任务并行地从服务器获取不同部分的数据包,最后再把这些分片组合成完整的文件保存至本地磁盘。这种方式不仅提高了传输效率还增强了用户体验感。 ```java public class FileDownloader { ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); public void downloadFile(String url, String destinationPath) throws Exception { URL website = new URL(url); HttpURLConnection connection = (HttpURLConnection)website.openConnection(); long fileSize = connection.getContentLengthLong(); int numThreads = Runtime.getRuntime().availableProcessors(); CountDownLatch latch = new CountDownLatch(numThreads); for(int i=0;i<numThreads;i++){ long startByte = ((fileSize/numThreads)*i)+(i==0 ? 0 : 1); long endByte = Math.min(((fileSize/numThreads)*(i+1)), fileSize)-1; DownloadTask task = new DownloadTask(startByte,endByte,url,destinationPath,latch,i,numThreads); executor.submit(task); } latch.await(); mergeFiles(destinationPath+".part", destinationPath, numThreads); cleanupPartialDownloads(destinationPath+".part", numThreads); executor.shutdownNow(); } } ``` 此段代码片段说明了一个基于固定大小线程池(`ExecutorService`)的异步文件下载器的设计思路[^2]。 #### 数据批量插入操作 对于数据库密集型的任务来说,合理运用多线程技术同样能带来显著的效果改进。比如在一个电商平台上执行订单记录入库的过程中,如果采用传统的单一线程方式逐条入可能会耗费大量时间;相反,借助于JDBC连接池以及Callable/Future机制就可以轻松完成高效稳定的批量化存储工作。 ```java List<Future<Boolean>> futures = new ArrayList<>(); for(Order order:listOfOrders){ Callable<Boolean> callable=new DatabaseInsertion(order); Future<Boolean> future=executor.submit(callable); futures.add(future); } // Check all tasks have completed successfully. boolean success=true; for(Future<Boolean> f:futures){ try{ if(!f.get()){ success=false; break; } }catch(Exception e){ logger.error(e.getMessage(),e); success=false; break; } } if(success){ commitTransaction(); }else{ rollbackTransaction(); } ``` 这段伪代码描述了一种通过提交一系列可调用对象给定数量的工作单元到线程池来进行并发处理的方法[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值