Java中的多类型参数任务执行:CallableWithMultiParams与SafeExecutor的设计与应用

150 阅读8分钟

1. 引言

针对高效的Java任务执行:SafeExecutor工具类的设计理念与应用 中需补充多参数类,则需要再次设计新接口和新方法进行支持

2. 设计目标

CallableWithMultiParams 和 SafeExecutor 的设计目标包括:

1. 支持多类型参数和返回值的任务:处理带多个不同类型参数和返回值的任务,提供更高的灵活性和强大功能。

3. 关键组件

3.1 CallableWithMultiParams 接口

CallableWithMultiParams 是一个泛型函数式接口,表示一个带有多个不同类型参数并返回结果的任务。该接口可以抛出异常。

这个接口将支持多个不同类型的参数,并返回一个结果。

package com.dereksmart.crawling.util.fuction;
/**
 * CallableWithMultiParams 是一个泛型接口,允许执行带有多个不同参数的任务并返回一个结果。
 *
 * @param <R> 返回值的类型
 * @param <P> 参数的类型
 * @Author derek_smart
 * @Date 2025/2/19 7:45
 */
@FunctionalInterface
public interface CallableWithMultiParams<R, P1, P2, P3> {
    R call(P1 param1, P2 param2, P3 param3) throws Exception;

    default R callWithRuntimeException(P1 param1, P2 param2, P3 param3) {
        try {
            return call(param1, param2, param3);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    default R callWithoutException(P1 param1, P2 param2, P3 param3) {
        try {
            return call(param1, param2, param3);
        } catch (Exception e) {
            return null;
        }
    }

    static <R, P1, P2, P3> CallableWithMultiParams<R, P1, P2, P3> empty() {
        return (param1, param2, param3) -> null;
    }
}

企业微信截图_17398525878856.png

3.2 SafeExecutor 工具类

将提供一组静态方法来安全地执行 CallableWithMultiParams,并处理异常。

package com.dereksmart.crawling.util.fuction;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 提供了一组静态方法来安全地执行同步和异步任务。
 * 这些方法在执行过程中捕获异常,并通过指定的异常处理器处理异常。
 * 该类提供了无返回值和有返回值的任务执行方法,并支持默认值和异常处理器的自定义。
 * @Author derek_smart
 * @Date 2025/2/18 8:50
 */
public final class SafeExecutor {
    /**
     * 默认的异常处理器,忽略所有异常。
     */
    public static final Consumer<Exception> IGNORE_EXCEPTION_HANDLER = e -> {
    };

    private SafeExecutor() {
        // Private constructor to prevent instantiation
    }
    // 同步方法

    /**
     * 执行一个无返回值的任务,并忽略任何异常。
     *
     * @param callable 要执行的任务
     */
    public static void executeWithoutException(VoidCallable callable) {
        execute(callable, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 执行一个无返回值的任务,并使用指定的异常处理器处理异常。
     *
     * @param callable         要执行的任务
     * @param exceptionHandler 异常处理器
     */
    public static void execute(VoidCallable callable, Consumer<Exception> exceptionHandler) {
        try {
            callable.call();
        } catch (Exception e) {
            handleException(e, exceptionHandler);
        }
    }

    /**
     * 执行一个有返回值的任务,并忽略任何异常。如果发生异常,返回 null。
     *
     * @param supplier 要执行的任务
     * @param <T>      返回值的类型
     * @return 任务的返回值,如果发生异常则返回 null
     */
    public static <T> T supplyWithoutException(Supplier<T> supplier) {
        return supplyWithoutException(supplier, null, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 执行一个有返回值的任务,并忽略任何异常。如果发生异常,返回指定的默认值。
     *
     * @param supplier     要执行的任务
     * @param defaultValue 默认返回值
     * @param <T>          返回值的类型
     * @return 任务的返回值,如果发生异常则返回默认值
     */
    public static <T> T supplyWithoutException(Supplier<T> supplier, T defaultValue) {
        return supplyWithoutException(supplier, defaultValue, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 执行一个有返回值的任务,并使用指定的异常处理器处理异常。如果发生异常,返回指定的默认值。
     *
     * @param supplier         要执行的任务
     * @param defaultValue     默认返回值
     * @param exceptionHandler 异常处理器
     * @param <T>              返回值的类型
     * @return 任务的返回值,如果发生异常则返回默认值
     */
    public static <T> T supplyWithoutException(Supplier<T> supplier, T defaultValue, Consumer<Exception> exceptionHandler) {
        try {
            return supplier.get();
        } catch (Exception e) {
            handleException(e, exceptionHandler);
        }
        return defaultValue;
    }


    /**
     * 异步执行一个无返回值的任务,并忽略任何异常。
     *
     * @param callable 要执行的任务
     */
    public static void executeAsyncWithoutException(VoidCallable callable) {
        executeAsync(callable, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 异步执行一个无返回值的任务,并使用指定的异常处理器处理异常。
     *
     * @param callable         要执行的任务
     * @param exceptionHandler 异常处理器
     */
    public static void executeAsync(VoidCallable callable, Consumer<Exception> exceptionHandler) {
        CompletableFuture.runAsync(() -> {
            try {
                callable.call();
            } catch (Exception e) {
                handleException(e, exceptionHandler);
            }
        });
    }

    /**
     * 异步执行一个有返回值的任务,并忽略任何异常。如果发生异常,返回 null。
     *
     * @param supplier 要执行的任务
     * @param <T>      返回值的类型
     * @return 一个 CompletableFuture,表示任务的返回值,如果发生异常则返回 null
     */
    public static <T> CompletableFuture<T> supplyAsyncWithoutException(Supplier<T> supplier) {
        return supplyAsyncWithoutException(supplier, null, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 异步执行一个有返回值的任务,并忽略任何异常。如果发生异常,返回指定的默认值。
     *
     * @param supplier     要执行的任务
     * @param defaultValue 默认返回值
     * @param <T>          返回值的类型
     * @return 一个 CompletableFuture,表示任务的返回值,如果发生异常则返回默认值
     */
    public static <T> CompletableFuture<T> supplyAsyncWithoutException(Supplier<T> supplier, T defaultValue) {
        return supplyAsyncWithoutException(supplier, defaultValue, IGNORE_EXCEPTION_HANDLER);
    }

    /**
     * 异步执行一个有返回值的任务,并使用指定的异常处理器处理异常。如果发生异常,返回指定的默认值。
     *
     * @param supplier         要执行的任务
     * @param defaultValue     默认返回值
     * @param exceptionHandler 异常处理器
     * @param <T>              返回值的类型
     * @return 一个 CompletableFuture,表示任务的返回值,如果发生异常则返回默认值
     */
    public static <T> CompletableFuture<T> supplyAsyncWithoutException(Supplier<T> supplier, T defaultValue, Consumer<Exception> exceptionHandler) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return supplier.get();
            } catch (Exception e) {
                handleException(e, exceptionHandler);
                return defaultValue;
            }
        });
    }

    // 新增方法:处理带多个参数和返回值的任务

    /**
     * 执行一个带多个参数和返回值的任务,并忽略任何异常。
     *
     * @param callable 要执行的任务
     * @param params 参数
     * @param <R> 返回值的类型
     * @param <P> 参数的类型
     * @return 任务的返回值,如果发生异常则返回 null
     */
    public static <R, P> R callWithoutException(CallableWithParams<R, P> callable, P... params) {
        return callWithoutException(callable, null, IGNORE_EXCEPTION_HANDLER, params);
    }

    /**
     * 执行一个带多个参数和返回值的任务,并使用指定的异常处理器处理异常。
     *
     * @param callable 要执行的任务
     * @param defaultValue 默认返回值
     * @param exceptionHandler 异常处理器
     * @param params 参数
     * @param <R>  返回值的类型
     * @param <P> 参数的类型
     * @return 任务的返回值,如果发生异常则返回默认值
     */
    public static <R, P> R callWithoutException(CallableWithParams<R, P> callable, R defaultValue, Consumer<Exception> exceptionHandler, P... params) {
        try {
            return callable.call(params);
        } catch (Exception e) {
            handleException(e, exceptionHandler);
            return defaultValue;
        }
    }

    /**
     * 异步执行一个带多个参数和返回值的任务,并忽略任何异常。
     *
     * @param callable 要执行的任务
     * @param params 参数
     * @param <R> 返回值的类型
     * @param <P> 参数的类型
     * @return 一个 CompletableFuture,表示任务的返回值,如果发生异常则返回 null
     */
    public static <R, P> CompletableFuture<R> callAsyncWithoutException(CallableWithParams<R, P> callable, P... params) {
        return callAsyncWithoutException(callable, null, IGNORE_EXCEPTION_HANDLER, params);
    }

    /**
     * 异步执行一个带多个参数和返回值的任务,并使用指定的异常处理器处理异常。
     *
     * @param callable 要执行的任务
     * @param defaultValue 默认返回值
     * @param exceptionHandler 异常处理器
     * @param params 参数
     * @param <R> 返回值的类型
     * @param <P> 参数的类型
     * @return 一个 CompletableFuture,表示任务的返回值,如果发生异常则返回默认值
     */
    public static <R, P> CompletableFuture<R> callAsyncWithoutException(CallableWithParams<R, P> callable, R defaultValue, Consumer<Exception> exceptionHandler, P... params) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return callable.call(params);
            } catch (Exception e) {
                handleException(e, exceptionHandler);
                return defaultValue;
            }
        });
    }

    /**
     * 处理异常的方法。如果提供了异常处理器,则调用它来处理异常。
     *
     * @param e 异常
     * @param exceptionHandler 异常处理器
     */
    private static void handleException(Exception e, Consumer<Exception> exceptionHandler) {
        if (Objects.nonNull(exceptionHandler)) {
            exceptionHandler.accept(e);
        }
    }




    // 同步执行带多个不同类型参数的任务
    public static <R, P1, P2, P3> R callWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, P1 param1, P2 param2, P3 param3) {
        try {
            return callable.call(param1, param2, param3);
        } catch (Exception e) {
            return null;
        }
    }

    public static <R, P1, P2, P3> R callWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, R defaultValue, Consumer<Exception> exceptionHandler, P1 param1, P2 param2, P3 param3) {
        try {
            return callable.call(param1, param2, param3);
        } catch (Exception e) {
            handleException(e, exceptionHandler);
            return defaultValue;
        }
    }

    // 异步执行带多个不同类型参数的任务
    public static <R, P1, P2, P3> CompletableFuture<R> callAsyncWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, P1 param1, P2 param2, P3 param3) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return callable.call(param1, param2, param3);
            } catch (Exception e) {
                return null;
            }
        });
    }

    public static <R, P1, P2, P3> CompletableFuture<R> callAsyncWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, R defaultValue, Consumer<Exception> exceptionHandler, P1 param1, P2 param2, P3 param3) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return callable.call(param1, param2, param3);
            } catch (Exception e) {
                handleException(e, exceptionHandler);
                return defaultValue;
            }
        });
    }
}

其中以下几个方法针对 CallableWithMultiParams进行调实现。


// 同步执行带多个不同类型参数的任务
public static <R, P1, P2, P3> R callWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, P1 param1, P2 param2, P3 param3) {
    try {
        return callable.call(param1, param2, param3);
    } catch (Exception e) {
        return null;
    }
}

public static <R, P1, P2, P3> R callWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, R defaultValue, Consumer<Exception> exceptionHandler, P1 param1, P2 param2, P3 param3) {
    try {
        return callable.call(param1, param2, param3);
    } catch (Exception e) {
        handleException(e, exceptionHandler);
        return defaultValue;
    }
}

// 异步执行带多个不同类型参数的任务
public static <R, P1, P2, P3> CompletableFuture<R> callAsyncWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, P1 param1, P2 param2, P3 param3) {
    return CompletableFuture.supplyAsync(() -> {
        try {
            return callable.call(param1, param2, param3);
        } catch (Exception e) {
            return null;
        }
    });
}

public static <R, P1, P2, P3> CompletableFuture<R> callAsyncWithoutException(CallableWithMultiParams<R, P1, P2, P3> callable, R defaultValue, Consumer<Exception> exceptionHandler, P1 param1, P2 param2, P3 param3) {
    return CompletableFuture.supplyAsync(() -> {
        try {
            return callable.call(param1, param2, param3);
        } catch (Exception e) {
            handleException(e, exceptionHandler);
            return defaultValue;
        }
    });
}

3.3使用示例

如何使用 SafeExecutor 和 CallableWithMultiParams 的示例。

// 同步执行任务
String result1 = SafeExecutor.callWithoutException(concatTask, "Number: ", 42, true);
System.out.println(result1); // 输出: Number: 42

// 同步执行任务,带默认值和异常处理器
String result2 = SafeExecutor.callWithoutException(concatTask, "Default Value", e -> System.err.println("Error: " + e.getMessage()), "Number: ", 42, false);
System.out.println(result2); // 输出: Default Value

// 异步执行任务
CompletableFuture<String> future1 = SafeExecutor.callAsyncWithoutException(concatTask, "Number: ", 42, true);
future1.thenAccept(resu -> System.out.println(result)); // 输出: Number: 42

// 异步执行任务,带默认值和异常处理器
CompletableFuture<String> future2 = SafeExecutor.callAsyncWithoutException(concatTask, "Default Value", e -> System.err.println("Error: " + e.getMessage()), "Number: ", 42, false);
future2.thenAccept(resu -> System.out.println(result)); // 输出: Default Value

通过这种设计,CallableWithMultiParams 接口可以支持不同类型的参数,SafeExecutor 工具类提供了对这些任务的同步和异步执行方法,并在发生异常时进行处理。

4. 结论

介绍了 CallableWithMultiParams 接口和 SafeExecutor 工具类的设计与实现。通过这些工具,可以提高代码的可读性、可维护性和灵活性。CallableWithMultiParams 支持带有不同类型参数的任务执行,而 SafeExecutor 提供了一组方法来安全地执行这些任务,并在发生异常时进行处理。这不仅简化了异常处理逻辑,还提供了对同步和异步任务的支持。