使用多线程,并获取返回结果的简介写法

本文介绍了在Java开发中处理需要依赖多线程返回数据的场景,通过线程池工具类和并行任务工具类的范型设计,详细展示了如何在多线程环境下获取任务执行的结果,并提供了相关的单元测试用例。

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

一、背景

在实际开发中,有些业务需要依赖多线程的返回数据,不是单纯的只执行业务逻辑就好。

二、demo

1.线程池工具类

@Slf4j
public class ThreadPoolUtils {

    private static ThreadPoolTaskExecutor poolTaskExecutor = null;

    private ThreadPoolUtils() {
    }

    public static ThreadPoolTaskExecutor getInstance() {
        try {
            if (poolTaskExecutor == null) {
                poolTaskExecutor = new ThreadPoolTaskExecutor();
                // 设置核心线程数
                poolTaskExecutor.setCorePoolSize(10);
                // 设置最大线程数
                poolTaskExecutor.setMaxPoolSize(100);
                // 设置队列容量
                poolTaskExecutor.setQueueCapacity(50000);
                // 设置线程活跃时间(秒)
                poolTaskExecutor.setKeepAliveSeconds(200);
                // 设置默认线程名称
                poolTaskExecutor.setThreadNamePrefix("taskExecutor-");
                // 设置拒绝策略 不在新线程中执行任务,而是有调用者所在的线程来执行
                poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
                // 等待所有任务结束后再关闭线程池
                poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
                // 加载
                poolTaskExecutor.initialize();
            } else {
                log.info("ThreadPool-"
                        + "activeCount=" + poolTaskExecutor.getThreadPoolExecutor().getActiveCount()
                        + ",taskCount=" + poolTaskExecutor.getThreadPoolExecutor().getTaskCount()
                        + ",completedTaskCount=" + poolTaskExecutor.getThreadPoolExecutor().getCompletedTaskCount()
                        + ",largestPoolSize=" + poolTaskExecutor.getThreadPoolExecutor().getLargestPoolSize()
                        + ",queueSize=" + poolTaskExecutor.getThreadPoolExecutor().getQueue().size());
            }
        } catch (Exception e) {
            log.error("[线程池使用] - 发生异常!", e);
        }

        return poolTaskExecutor;
    }

2. 并行任务工具类(范型、多线程)

@Slf4j
public class ParallelUtil {
    @FunctionalInterface
    public interface ParallelFunction<T> extends Supplier<T> {

    }

    @Data
    @Accessors(chain = true)
    public static class ParallelJob<T> {

        private ParallelFunction<T> function;
        private T result;
    }

    public static void execute(@NonNull List<ParallelJob> jobs) {
        log.info("并行任务工具类 - 开始执行,任务数:{}", jobs.size());
        CountDownLatch countDownLatch = new CountDownLatch(jobs.size());
        for (int num = 0; num < jobs.size(); num++) {
            int tempNum = num + 1;
            ParallelJob job = jobs.get(num);
            ThreadPoolUtils.getInstance().execute(() -> {
                try {
                    log.info("并行任务工具类 - 第{}个任务执行中..", tempNum);
                    // 处理业务逻辑
                    job.setResult(job.getFunction().get());
                } catch (Exception e) {
                    log.info("并行任务工具类 - 第{}个任务执行失败e:{}", tempNum, e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("并行任务工具类 - 执行完成!");

    }

    public static void execute(@NonNull ParallelJob... jobs) {
        log.info("并行任务工具类 - 开始执行,任务数:{}", jobs.length);
        Arrays.stream(jobs).parallel().forEach(job ->
                job.setResult(job.getFunction().get())
        );
        log.info("并行任务工具类 - 执行完成!");
    }

}

3.单元测试

 @Test
    public void test1() {
        StopWatch duration = new StopWatch();
        duration.start();

        // 任务定义
        String mobile = "12345678";
        ParallelUtil.ParallelJob<List<String>> userNamesJob = new ParallelUtil.ParallelJob<List<String>>().setFunction(() -> {
            return queryUserNamesByMobile(mobile);
        });

        ParallelUtil.ParallelJob<Integer> userCountJob = new ParallelUtil.ParallelJob<Integer>().setFunction(() -> {
            return getCountNum();
        });
        List<ParallelUtil.ParallelJob> jobs = new ArrayList<>();
        jobs.add(userNamesJob);
        jobs.add(userCountJob);

        // 执行任务
//        ParallelUtil.execute(jobs);
        ParallelUtil.execute(userNamesJob,userCountJob);

        // 结果输出
        System.out.printf("执行耗时:" + duration.getTime(TimeUnit.MILLISECONDS) + ":userNames:" + JSON.toJSONString(userNamesJob.getResult()) + ",userCount:" + userCountJob.getResult());

    }

    private Integer getCountNum() {
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 3;
    }

    private List<String> queryUserNamesByMobile(String mobile) {
        // 业务处理
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Arrays.asList("张三", "李四", "王五");

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值