Java线程池工具类

110 阅读3分钟

线程池工具类?

不是谁都会用,要什么工具类,就算要、又能怎么样。ok

先看使用,简单些

// 正常
ThreadPoolExecutor threadPoolExecutor = SpringUtils.getBean("BfThreadPool"); 
threadPoolExecutor.execute(() -> { // 业务代码 });


// 我的
new BfThreadPoolUtils<>().setName(" 请求数据")
        .addConsumers(integer -> { // 业务代码 }, "数据进行入库")
        .addConsumers(integer -> { // 业务代码 }, "数据进行入库")
        .addConsumers(integer -> { // 业务代码 }, "数据进行入库")
        .Run();

这里觉得没什么,都一样嘛,比如复杂些:主线程等等子线程

//正常

ThreadPoolExecutor threadPoolExecutor = SpringUtils.getBean("BfThreadPool"); 
CountDownLatch latch = new CountDownLatch(3);
threadPoolExecutor.execute(() -> { 
    // 业务代码
    try {
        integerConsumer.accept(finalI);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        latch.countDown();
    }
});
threadPoolExecutor.execute(() -> { 
    // 业务代码
    try {
        integerConsumer.accept(finalI);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        latch.countDown();
    }
});
threadPoolExecutor.execute(() -> { 
    // 业务代码
    try {
        integerConsumer.accept(finalI);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        latch.countDown();
    }
});

 try {
    // 主线程等待所有任务完成
    latch.await(120l,TimeUnit.SECONDS);
 } catch (Exception e) {
    e.printStackTrace();
 } 
 log.info(explain + "完成!");

我的

new BfThreadPoolUtils<>().setName(" 请求数据")
    .addConsumers(integer -> {
        // 业务代码
    }, "数据进行入库")
    .addConsumers(integer -> {
        // 业务代码
    }, "数据进行入库")
    .addConsumers(integer -> {
        // 业务代码
    }, "数据进行入库")
    // 主线程等等子线程
    .openMainThreadAwait(data -> {
    // 子线程中有出现异常操作
    }, errorData -> {
    // 主线程等等异常操作
    }, "未达到指定的请求数之前出现异常").Run();
 
log.info(explain + "完成!");

主要是每次都要写try-catch等等一长串的代码,有必要嘛,咳,正常写还是有必要的,但我们可以简化些。

下面是这个工具类

/**
 * 线程池工具类
 */
@Slf4j
public class HyThreadPoolUtils<T> {

    //返回值不处理子任务(子任务有方法名)
    private CopyOnWriteArrayList<Map<String, Function<Integer, T>>> functionsName = new CopyOnWriteArrayList<>();
    //返回值处理方法(仅对于有返回值的子任务)
    private Function<List<T>, Object> resultFunction;
    //无返回值子任务(子任务有方法名)
    private CopyOnWriteArrayList<Map<String, Object>> consumersName = new CopyOnWriteArrayList<>();
    // 任务名称
    private String name;
    // 让一个线程在达到指定的请求次数之前等待(默认null)
    private CountDownLatch latch;
    // 是否存在异常
    AtomicReference<Boolean> isError = new AtomicReference<>(false);
    // 子线程出现异常,放入传入的参数
    private CopyOnWriteArrayList<Object> errorData = new CopyOnWriteArrayList<>();
    // 线程池
    private ThreadPoolExecutor threadPoolExecutor;
    // 有返回值方法的 返回值
    private Object object;
    // 子线程出现异常处理方法
    private Consumer childThreadErrorMethod;
    // CountDownLatch等待出现异常处理方法
    private Consumer countDownLatchErrorMethod;
    // CountDownLatch等待出现异常处理方法,异常信息说明
    private String countDownLatchErrorMethodExplain;
    // 是否开启主线程等待子线程执行完成
    private Boolean ifMainThreadAwait = false;


    /**
     * 运行方法(必须要执行此方法才能运行)
     *
     * @return
     */
    public HyThreadPoolUtils Run() {
        // 总任务个数
        int numberSubtasks = functionsName.size() + consumersName.size();
        // 执行三种方法
        name = getName(this.name);

        // 开启主线程等待子线程,则要进行初始化CountDownLatch
        if (this.ifMainThreadAwait) {
            // 让一个线程在达到指定的请求次数之前等待
            this.latch = new CountDownLatch(numberSubtasks);
        }

        // 获取到线程池
        threadPoolExecutor = SpringUtils.getBean("HyThreadPool");

        // 执行无返回方法
        threadExecution();

        // 执行有返回方法
        List<T> resultList = threadExecutionResult();

        if (resultFunction != null) {
            // 处理结果然后返回
            object = resultFunction.apply(resultList);
        }else {
            object = resultList;
        }

        // 进行主线程等待
        if (ifMainThreadAwait) {
            try {
                // 主线程等待所有任务完成
                latch.await(120l,TimeUnit.SECONDS);
                // 获取线程执行过程中是否有异常
                // 其中一个子线程出现异常,进行对应操作
                if (isError.get()) {
                    // 自定义操作方法
                    childThreadErrorMethod.accept(errorData);
                }
            } catch (Exception e) {
                // 主线程等待超时,出现异常,事务回滚
                log.error(name + " ," + countDownLatchErrorMethodExplain + ", 主线程等待超时,出现异常,异常:" + e.toString());
                // 自定义操作方法
                countDownLatchErrorMethod.accept(errorData);
                e.printStackTrace();
            }
        }
        return this;
    }


    /**
     * 执行无返回方法
     */
    public void threadExecution() {
        for (int i = 0; i < consumersName.size(); i++) {
            int finalI = i;
            // 执行方法
            threadPoolExecutor.execute(() -> {
                String subtaskName = String.valueOf(consumersName.get(finalI).get("name"));
                Consumer<Integer> integerConsumer = (Consumer<Integer>) consumersName.get(finalI).get("method");

                try {
                    integerConsumer.accept(finalI);
                } catch (Exception e) {
                    isError.set(true);
                    errorData.add(consumersName.get(finalI).get("data"));
                    subtaskName = StrUtil.isEmpty(subtaskName) ? String.valueOf(finalI) : subtaskName;
                    log.error("-->任务名称:" + name + ":" + ",无返回值,子任务:" + subtaskName + ",执行异常:" + e.toString());
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            });
        }
    }


    /**
     * 执行有返回方法
     *
     * @return
     */
    public List<T> threadExecutionResult() {
        // 返回结果
        List<T> resultList = new ArrayList<>();
        List<FutureTask<T>> futureTaskList = new ArrayList<>();
        for (int i = 0; i < functionsName.size(); i++) {
            int finalI = i;
            // 执行方法
            FutureTask futureTask = new FutureTask<T>(() -> {
                T apply = null;
                String subtaskName = "";
                try {
                    Function<Integer, T> integerTFunction = functionsName.get(finalI).values().iterator().next();
                    apply = integerTFunction.apply(finalI);
                    return apply;
                } catch (Exception e) {
                    this.isError.set(true);
                    subtaskName = StrUtil.isEmpty(subtaskName) ? String.valueOf(finalI) : subtaskName;
                    log.error("-->任务名称:" + name + ":" + ",有返回值,不处理子任务:" + subtaskName + ",执行异常:" + e.toString());
                    e.printStackTrace();
                    return null;
                } finally {
                    this.latch.countDown();
                }
            });
            futureTaskList.add(futureTask);
            threadPoolExecutor.submit(futureTask);
        }

        // 获取结果
        for (FutureTask<T> futureTask : futureTaskList) {
            try {
                // get方法会阻塞,直到获取结果为止
                // futureTask.get();
                resultList.add(futureTask.get(60, TimeUnit.SECONDS));
            } catch (InterruptedException e) { // 线程被中断将会进入此处
                e.printStackTrace();
                log.info("-->中断异常");
                throw new RuntimeException("系统异常!");
            } catch (ExecutionException e) { // 线程执行异常将会进入此处
                e.printStackTrace();
                log.info("-->执行异常");
                throw new RuntimeException("系统异常!");
            } catch (TimeoutException e) { // 获取结果超时将会进入此处
                e.printStackTrace();
                log.info("-->超时异常");
                throw new RuntimeException("系统异常!");
            }
        }
        return resultList;
    }


    /**
     * 获取任务名称
     *
     * @param prefix 任务名称前缀
     * @return
     */
    public String getName(String prefix) {
        String id = String.valueOf(HyIdUtils.getNextId());
        return StrUtil.isEmpty(prefix) ? id : prefix + ":" + id;
    }

    /**
     * ‘添加有返回值任务
     * @param function
     * @param name
     * @return
     */
    public HyThreadPoolUtils addFunctions(Function<Integer, T> function, String name) {
        functionsName.add(new HashMap<String, Function<Integer, T>>() {{
            put(name, function);
        }});
        return this;
    }

    /**
     * 添加无返回值任务
     * @param consumer
     * @param name
     * @return
     */
    public HyThreadPoolUtils addConsumers(Consumer<Integer> consumer, String name) {
        consumersName.add(new HashMap<String, Object>() {{
            put("method", consumer);
            put("name", name);
        }});
        return this;
    }

    /**
     * 添加无返回值任务
     * @param consumer
     * @param name
     * @param data 可以通过getErrorData()方法获取出现异常的子线程中的data数据
     * @return
     */
    public HyThreadPoolUtils addConsumers(Consumer<Integer> consumer, String name, Object data) {
        consumersName.add(new HashMap<String, Object>() {{
            put("method", consumer);
            put("name", name);
            put("data", data);
        }});
        return this;
    }

    /**
     * 添加有返回值任务,所有任务执行完成后进行处理的方法
     * @param resultFunction
     * @return
     */
    public HyThreadPoolUtils addResultFunctions(Function<List<T>, Object> resultFunction) {
        this.resultFunction = resultFunction;
        return this;
    }

    /**
     * 设置任务名称
     * @param name
     * @return
     */
    public HyThreadPoolUtils setName(String name) {
        this.name = name;
        return this;
    }

    /**
     * 获取子线程是否有异常
     * @return
     */
    public AtomicReference<Boolean> getIsError() {
        return isError;
    }

    /**
     * 执行主线程等待子线程
     * @param childThreadErrorMethod
     * @param countDownLatchErrorMethod
     * @param countDownLatchErrorMethodExplain
     * @return
     */
    public HyThreadPoolUtils openMainThreadAwait(Consumer childThreadErrorMethod, Consumer countDownLatchErrorMethod, String countDownLatchErrorMethodExplain) {
        this.ifMainThreadAwait = true;
        this.childThreadErrorMethod = childThreadErrorMethod;
        this.countDownLatchErrorMethod = countDownLatchErrorMethod;
        this.countDownLatchErrorMethodExplain = countDownLatchErrorMethodExplain;
        return this;
    }

    /**
     * 获取有参方法返回结果
     * @return
     */
    public Object getObject() {
        return object;
    }

    /**
     * 获取放入线程前的,自定义数据
     * @return
     */
    public List<Object> getErrorData() {
        return this.errorData;
    }

最后,仅自己学习记录所用,如有不对,或者错误也欢迎指正,哈哈哈哈

感谢:

# 万字详解 java 线程池,让我们的高并发程序更稳健