ThreadPoolExecutor实现多线程+实战

当接口业务逻辑复杂且SQL优化空间有限时,可以采用多线程进行并行处理。文章介绍了如何使用Java的ThreadPoolExecutor创建线程池,以及提交有返回值的Callable任务,以提高处理效率。示例代码展示了在Controller层如何测试多线程并发和异步处理,以及Callable任务的使用方法。

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

平时项目开发中,接口业务逻辑复杂,sql也没有了优化空间,这时我们就可以用到多线程来并行处理,提升接口效率,这里做个记录

使用场景

  1. 定时任务批量处理数据

  2. 复杂逻辑需要同时满足多个条件判断

  3. MQ消费

  4. 日志异步记录

多线程使用我归为两类

  • 多线程无返回值
  • 多线程有返回值

一、有返回值多线程实现

   封装一个通用工具类AsyncThreadUtils


public class AsyncThreadUtils {

    private static final int corePoolSize = Runtime.getRuntime().availableProcessors();//CPU核心数
    private static final int maximumPoolSize = corePoolSize * 2;
    private static long keepAliveTime = 1;
    private static TimeUnit keepAliveTimeUnit = TimeUnit.MINUTES;
    private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1024);
    private static RejectedExecutionHandler rejectedHandler = new ThreadPoolExecutor.CallerRunsPolicy();

    /**
     * corePoolSize : 线程池核心线程数,最好默认CPU核心数
     * maximumPoolSize : 线程池最大线程数,最好是核心线程数的两倍,太多会引起线程切换
     * keepAliveTime : 大于核心线程数的空闲线程存活时间
     * keepAliveTimeUnit : 空闲线程存活时间的单位(秒、分钟、小时等等)
     * workQueue : 线程池有界队列,新任务没有可用线程处理时会把任务放到该队列中,等待被处理
     * rejectedHandler : 拒绝处理策略,默认直接丢弃并抛出异常-AbortPolicy,调用者线程直接处理-CallerRunsPolicy
     */
    private static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            corePoolSize,
            maximumPoolSize,
            keepAliveTime,
            keepAliveTimeUnit,
            workQueue,
            rejectedHandler
    );

    /**
     * 直接提交任务,无返回值
     * @param task
     */
    public static void submit(Runnable task){
        poolExecutor.submit(task);
    }

    /**
     * 提交任务,返回泛型结果
     * @param task
     * @param <T>
     * @return
     */
    public static <T> Future<T> submit(Callable<T> task){
        return poolExecutor.submit(task);
    }
}

   Controller层测试多线程


@RestController
@RequestMapping(value = "/threadPool")
public class ThreadPoolController {
    private static final Log LOG = LogFactory.getLog(ThreadPoolController.class);

    @ApiOperation("测试多线程并发处理")
    @RequestMapping(value = "/ceshiThread")
    public ResultMsg ceshiThread(){
        try {
            int finalI = 0;
            for (int i = 0; i < 20; i++) {
                finalI ++;
                int finalI1 = finalI;
                AsyncThreadUtils.submit(() -> c(finalI1));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResultUtil.success(null);
    }

    @ApiOperation("测试多线程异步处理")
    @RequestMapping(value = "/ceshiAsync")
    public ResultMsg ceshiAsync(){
        int a = 1;
        try {
            long currentTimeMillis = System.currentTimeMillis();
            a();
            b();
            long currentTimeMillis1 = System.currentTimeMillis();
            LOG.error("同步耗时:"+ (currentTimeMillis1 - currentTimeMillis));
            long currentTimeMillis2 = System.currentTimeMillis();
            Future<Boolean> submit = AsyncThreadUtils.submit(() -> a());
            Future<Boolean> submit2 = AsyncThreadUtils.submit(() -> b());
            Boolean aBoolean = submit.get();
            Boolean aBoolean2 = submit2.get();
            long currentTimeMillis3 = System.currentTimeMillis();
            LOG.error("异步耗时:"+ (currentTimeMillis3 - currentTimeMillis2));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResultUtil.success(null);
    }

    private Boolean a(){
        try {
            Thread.sleep(3000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return false;
    }

    private Boolean b(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return false;
    }

    private Boolean c(int count){
        try {
            Thread.sleep(5000);
            LOG.error("打印:"+ count);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return false;
    }
}

二、实现有返回值多线程

package com.deppon.cc.service.impl;
import java.util.concurrent.*;

public class CallableExample {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建一个ExecutorService,这里使用固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);
        // 提交Callable任务给ExecutorService
        Future<String> future = executor.submit(new MyCallable());
        Future<String> future1 = executor.submit(new MyCallable1());
        // 在任务完成之前,主线程可以做其他事情

        // 获取Callable的返回值
        String result = future.get(); // 这会阻塞,直到任务完成
        String result1 = future1.get();
        // 关闭ExecutorService
        executor.shutdown();
    }

    static class MyCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            // 模拟耗时的计算
            Thread.sleep(2000);
            return "Hello from Callable!";
        }
    }

    static class MyCallable1 implements Callable<String> {
        @Override
        public String call() throws Exception {
            // 模拟耗时的计算
            Thread.sleep(2000);
            return "Hello from Callable!";
        }
    }
}

多线程并行处理任务可以提升服务器资源使用率,同时可以提高接口响应效率,值得推荐!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值