【Java】利用多线程处理大量任务

前言

  当我们在工作中遇到需要通过程序处理大量数据或者一些耗时任务时,使用单线程处理效率非常低,这时候我们一般都会用多线程来处理,本篇详细讲解如何利用多线程来处理大量任务。
  从任务的性质来讲,一般分为CPU密集型、I/O密集型、混合型、内存型等,不同类型的任务在利用线程池时需要设置不同的核心线程数来达到最佳效果,实际中大家根据任务情况选择合适的核心线程数,以下是示例:

说明

本例使用自定义线程池处理cpu密集型任务,假设有100个任务需要处理,每个任务耗时1s,根据核心线程数量(cpuCoreCnt)将任务拆分成cpuCoreCnt份,每份使用一个线程处理。大家可以将下述例子直接复制使用,线程池相关参数根据自身项目情况自行设置即可。

import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
 * *author:你住过的屋檐
 */
@Slf4j
public class DataHandle {
    static  int cpuCoreCnt = Runtime.getRuntime().availableProcessors(); //获取服务器CPU核心数
    static  int corePoolSize = cpuCoreCnt;      // 核心线程数
    static  int maximumPoolSize = cpuCoreCnt;   // 最大线程数
    static  int keepAliveTime = 30;             // 非核心线程的空闲存活时长(分钟)
    static  int queueCapacity = 9999;           // 队列最大长度
    public static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(queueCapacity);
    static ThreadPoolExecutor threadPool;
    static{
        threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES, queue);
    }
    /**
     * 处理数据
     * @param handleList
     */
    public static void task(List<Integer> handleList){
        //处理数据
        handleList.forEach(item->{
            try {
                //模拟业务每条数据处理1s中
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
    public static void main(String[] args) {
        //数据集(假如有100条数据,每个数据处理需要1s)
       List<Integer> dataList = new ArrayList<>();
        for (int i =1; i <=100; i++) {
            dataList.add(i);
        }
        log.info("当前cpu核数:{}",cpuCoreCnt);
        //通过对核心数取余来计算每个线程需要处理的数据量大小
        int size = dataList.size() % cpuCoreCnt > 0 ? dataList.size() / cpuCoreCnt +1 : dataList.size() / cpuCoreCnt;
        // 用于存储所有任务的Future
        List<Future> futureList = new ArrayList<>();
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < cpuCoreCnt; i++) {
            //获取每个线程要处理的数据集
            List<Integer> handleList = dataList.subList(i * size, Math.min(dataList.size(), i * size + size));
            //创建异步任务添加到线程池,这里使用jdk8的CompletableFuture
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                //数据集处理任务
                task(handleList);
            }, threadPool);
            //将CompletableFuture添加到futureList用于计算耗时
            futureList.add(completableFuture);
        }
        // 非阻塞等待所有任务完成
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).thenRunAsync(() -> {
            long endTime = System.currentTimeMillis();
            long totalTime = endTime - startTime;
            System.out.println("处理完成,耗时: " + totalTime + "毫秒");
            //关闭线程池
            threadPool.shutdown();
        }, threadPool);
    }
}

执行结果

在这里插入图片描述

根据执行结果大概耗时13s,如果是单线程处理则需要100s,效率提升了数倍。

完结撒花,欢迎订阅专栏!

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值