Gobrs-Async Gobrs-Async
🚘首页
🧧指南
🍭FAQ
💖支持
🚨加入群聊
🍅GitEE (opens new window)
GitHub (opens new window)
🚘首页
🧧指南
🍭FAQ
💖支持
🚨加入群聊
🍅GitEE (opens new window)
GitHub (opens new window)
  • 🥪项目特性

    • 🍿框架设计
  • 🎒框架设计

    • 🥧简介
    • 🍿框架设计
    • 🍍框架落地
  • 🍖快速开始

    • 🍔快速上手
    • 🌭框架集成
    • 🥤启动流程
    • 🍪流程参数
    • 🏝流程结果
  • 🥘规则配置

    • 🍅规则配置
  • 🥊任务类型

    • 🍅普通任务
    • 💥重试任务
    • ☄️事务任务
    • 🌈超时任务
    • ⛱方法任务
      • 何为方法任务
      • 开启方法任务
      • 说明
        • 声明方法任务组件
      • 方法任务
        • 匹配模式-取参
        • 总线模式-取参
      • 其它配置
        • 示例
        • 注解说明
      • 完整案例
  • 🔥高级特性

    • 💐线程复用
    • 🧋运行日志
    • 🍜规则热更新
    • 🍑任务中断
    • 🌺可选子流程
    • 🌹状态流程
    • 🍒异常拦截
    • 🥪全局任务拦截
    • 🍏自定义线程池
    • 🍒可选的执行流程
  • 🚐插件

    • 🛻插件简介
    • 🏚监控系列

      • ⛽️skywalkiing
      • 🏖hippo4j
    • 🛸日志系列

      • 🚧全链路traceId
  • 🍿性能考量

    • 🍎框架压测
    • 🍹框架对比
    • 🧅版本号手册
  • 🌕展望

    • 🍊展望
  • 🍯联系作者

    • 🥐加群沟通
目录

⛱方法任务

# 何为方法任务

相信看到这里的小伙伴大概已经了解Gobrs-Async如何创建一个普通任务(创建一个类继承自AsyncTask),那么有的小伙伴觉的业务不是很复杂,只是单纯的多线程开发,不想 开启一个任务就创建一个类。这违背了多线程简单上手的初衷。 那么这种场景下如何快速完成多线程开发,并且具备管理多线程(重试、回调、监控、超时)的能力呢?

# 开启方法任务

开启方法任务很简单(默认不开启方法任务,完全按照小伙伴开发喜好设计),只需要在SpringBoot启动类中编写 @EnabledMethodTask 注解即可开启方法任务

@EnabledMethodTask
@SpringBootApplication
public class GobrsAsyncTestApplication {
    /**
     * The entry point of application.
     * @param args the input arguments
     */
    public static void main(String[] args) {
        SpringApplication.run(GobrsAsyncTestApplication.class, args);
    }
}

# 说明

方法任务是通过一个方法开启一个任务。 适合业务不太复杂需要开启多线程同时管理多线程的场景。

# 声明方法任务组件

所谓的方法任务组件: 方法任务所在的类。

只需要在需要想要开启方法任务的业务 service 中编码 @MethodComponent注解,则标识该类为 Gobrs-Async的方法任务组件。

提示

@MethodComponent 注解默认集成Spring的 @Component注解,无须重复引入。

# 方法任务

只需要使用 @MethodTask 注解到所要开启任务的方法上即可, 同时注解了@MethodTask的方法也兼容直接当作普通方法调用,也就是说对参数没有任何限制。

# 匹配模式-取参

所谓匹配模式即为 任务流程在发起调用时,会传递给每一个任务所需要的参数, 在传递参数时,方法任务的参数传递需要使用ParamsTool.asParams 方法包裹。 否则无法在 方法任务参数中进行映射。如果未使用 ParamsTool.asParams 方法包裹。则可以使用总线模式从TaskSupport获取参数。

提示

如果参数不匹配(数量不匹配、类型不匹配), 会打印对应状态日志。并不会抛出异常。

调用流程如下所示:

    @SneakyThrows
    @Test
    public void launcher() {
        Map<String, Object> params = new HashMap<>();
        /**
         * normal 任务参数 无法进行参数映射 需要在方法任务参数中注入 TaskSupport 从 TaskSupport中 获取参数值
         */
        params.put("normal", new HashMap<>());
        /**
         * normal2 可以直接通过参数映射进行匹配取值。 需要注意的是 参数类型需要匹配正确, 否则参数获取为空
         */
        params.put("normal2", ParamsTool.asParams("support seize a seat", "context"));

        AsyncResult asyncResult = gobrsAsync.go("launcher", () -> params, 300000);
        final Map<String, TaskResult> resultMap = asyncResult.getResultMap();
        Assertions.assertEquals(resultMap.get("normal").getResult(), CaseMethodTaskOne.TASK_1_RESULT);
    }

方法任务参数映射如下所示:

 @MethodTask(name = "normal")
    public String normal(TaskSupport taskSupport) throws InterruptedException {
        String context1 = taskSupport.getParam("normal", String.class);
        Thread.sleep(1000);
        Assertions.assertThat(context1).isEqualTo("context");
        return TASK_1_RESULT;
    }

    /**
     * Normal 2 string.
     *
     * @return the string
     */
    @SneakyThrows
    @MethodTask
    public String normal2(String param1, String param2, TaskSupport support) {
        Assertions.assertThat(param1).isEqualTo("context");
        /**
         * 获取 task1 的返回结果
         */
        String task1Result = support.getResult("normal", String.class);
        Assertions.assertThat(task1Result).isEqualTo(TASK_1_RESULT);
        Thread.sleep(1000);
        return "task2";
    }

# 总线模式-取参

如果开发者想获取 Gobrs-Async内部中的当前方法任务所依赖任务的返回结果 或者 获取当前方法任务外部传递进来的参数, 则需要参数在方法参数中添加 TaskSupport。如下所示:

    @MethodTask(name = "normal")
    public String normal(TaskSupport taskSupport) throws InterruptedException {
        String context1 = taskSupport.getParam("normal", String.class);
        Thread.sleep(1000);
        Assertions.assertThat(context1).isEqualTo("context");
        return TASK_1_RESULT;
    }
  • 获取方法任务参数: TaskSupport#getParam(String taskName, Class<T> class) 方法即可获取
  • 获取所依赖任务的返回结果: TaskSupport#getResult(String taskName, Class<T> class) 方法即可获取

# 其它配置

# 示例

    @SneakyThrows
    @MethodTask(invoke = @Invoke(onFail = "demote", rollback = "Exception"), config = @MethodConfig(retryCount = 10))
    public void throwException() {
        System.out.println("will throwException");
        throw new RuntimeException("throwException test");
    }

# 注解说明

  • @MethodComponent 标识类为方法任务组件, 注解在类上。
  • @MethodTask 方法任务标识, 注解在方法上 。参数如下:
    • name: 方法任务名称需与 Gobrs-Async 配置文件中的 task 名称匹配,如果不编写。则默认取该注解方法的名称(会判重)
    • invoke: 配置方法任务的 回调方法(成功、失败、回滚、必要条件)与 @Task注解中的配置项匹配
    • config: 配置方法任务的任务属性(超时时间、重试次数、描述、是否具备事务属性、异常是否继续执行、描述)

# 完整案例

配置

gobrs:
  async:
    config:
      rules:
        - name: "launcher"
          content: "normal->normal2"
        - name: "methodRetry"
          content: "throwException"
        - name: "methodTimeout"
          content: "timeout"
        - name: "rollback"
          content: "rollback1->rollback2->rollback3"
          transaction: true

任务编码

@MethodComponent
public class CaseMethodTaskOne {

    /**
     * The constant TASK_1_RESULT.
     */
    public static final String TASK_1_RESULT = "task1_result";

    /**
     * Case 1.
     *
     * @return the string
     * @throws InterruptedException the interrupted exception
     */
    @MethodTask(name = "normal")
    public String normal(TaskSupport taskSupport) throws InterruptedException {
        String context1 = taskSupport.getParam("normal", String.class);
        Thread.sleep(1000);
        Assertions.assertThat(context1).isEqualTo("context");
        return TASK_1_RESULT;
    }

    /**
     * Normal 2 string.
     *
     * @return the string
     */
    @SneakyThrows
    @MethodTask
    public String normal2(String param1, String param2, TaskSupport support) {
        Assertions.assertThat(param1).isEqualTo("context");
        /**
         * 获取 task1 的返回结果
         */
        String task1Result = support.getResult("normal", String.class);
        Assertions.assertThat(task1Result).isEqualTo(TASK_1_RESULT);
        Thread.sleep(1000);
        return "task2";
    }

    /**
     * Throw exception.
     */
    @SneakyThrows
    @MethodTask(invoke = @Invoke(onFail = "demote", rollback = "Exception"), config = @MethodConfig(retryCount = 10))
    public void throwException() {
        System.out.println("will throwException");
        throw new RuntimeException("throwException test");
    }

    /**
     * Demote.
     */
    public void demote() {
        System.out.println("task2 execute fail");
    }

    /**
     * Timeout.
     */
    @SneakyThrows
    @MethodTask
    public void timeout() {
        Thread.sleep(30000);
    }


    /**
     * Rollback 1.
     */
    @SneakyThrows
    @MethodTask(invoke = @Invoke(rollback = "rool1"))
    public void rollback1() {
        System.out.println("rooback1");
        Thread.sleep(1000);
    }


    /**
     * Rollback 2.
     */
    @SneakyThrows
    @MethodTask(invoke = @Invoke(rollback = "rool2"))
    public void rollback2() {
        System.out.println("rollback2");
        Thread.sleep(1000);
    }


    /**
     * Rollback 3.
     */
    @SneakyThrows
    @MethodTask(invoke = @Invoke(rollback = "rool1"), config = @MethodConfig(callback = true))
    public void rollback3() {
        System.out.println("rollback3");
        Thread.sleep(1000);
        System.out.println(1 / 0);

    }

    /**
     * Roo 1.
     */
    public void rool1() {
        System.out.println("rool1 start ....");
    }

    /**
     * Roo 2.
     */
    public void rool2() {
        System.out.println("rool2 start ....");
    }
}
Last Updated: 1/7/2023, 1:49:29 AM
🌈超时任务
💐线程复用

← 🌈超时任务 💐线程复用→

最近更新
更多文章>
Gobrs-Async | Copyright © 2022-2023 Memorydoc | Apache License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式