前言
如果你平时经常写 Java 并发代码,大概率遇到过这些问题:
- 多个并发任务的生命周期散落在不同地方,最终很难统一管理
- 超时、取消、失败传播经常需要手写,逻辑一复杂就容易遗漏
CompletableFuture足够灵活,但业务链路一长,代码可读性会明显下降- 想做观测时,还要自己补日志、指标、Tracing 和慢任务告警
ThreadForge 想解决的就是这类问题:把并发任务放进一个结构化作用域里,让默认行为更安全,让代码更容易推理。
最近发布的 1.2.0,是这个项目推进核心并发模型的一次重要版本。
除了原有的 ThreadScope、超时、重试、上下文传播、OpenTelemetry 等基础能力,这次主要补齐了三块内容:
- 高阶编排 API
- 可直接运行的 examples 和 benchmarks
- 更完整的观测扩展能力
Maven Central 坐标如下:
<dependency>
<groupId>pub.lighting</groupId>
<artifactId>threadforge-core</artifactId>
<version>1.2.0</version>
</dependency>
高阶编排终于来了
之前 ThreadForge 已经可以比较优雅地处理:
- scope 级超时
- per-task timeout
- retry
- cancellation
- context propagation
- task lifecycle hook
这次 1.2.0 继续补上了多个任务并发执行后的结果处理能力。
比如这些场景:
- 多个数据源同时请求,只要第一个成功结果
- 多副本请求里,只要有 2 个成功就可以继续
- 主请求先发,如果变慢,再补一个 hedged request
过去这些逻辑通常需要业务层自己写取消、状态判断和异常处理。现在 ThreadForge 把这些常见模式抽成了新的编排 API。
1.2.0 新增了两个核心类型:
JoinStrategyScopeJoiner
1. firstSuccess
firstSuccess 会在第一个任务成功后立即返回结果,并自动取消其余尚未完成的任务。
try (ThreadScope scope = ThreadScope.open()) {
String winner = scope.joiner().firstSuccess(
() -> providerA(),
() -> providerB(),
() -> providerC()
);
}
这个模式非常适合:
- 多机房兜底
- 多 Provider fallback
- 只需要首个成功结果即可继续的查询类请求
2. quorum(n)
quorum(n) 会在成功任务数达到指定阈值后返回结果。
try (ThreadScope scope = ThreadScope.open()) {
List<String> result = scope.joiner().quorum(
2,
() -> replicaA(),
() -> replicaB(),
() -> replicaC()
);
}
这个能力适合:
- 多副本读取
- 部分成功即可继续推进的容错查询
- 需要 quorum 机制的投票式结果处理
3. hedged(delay)
hedged(delay) 会先发起主请求,如果超过指定延迟仍未完成,再放出 backup request。
try (ThreadScope scope = ThreadScope.open()) {
String result = scope.joiner().hedged(
Duration.ofMillis(50),
() -> primaryCall(),
() -> backupCall()
);
}
这个模式主要用来削尾延迟。
当你依赖外部服务,并且对方存在偶发长尾时,hedged request 会很实用。
4. 复用原有 scope 语义
这次 API 设计里最重要的一点,是它继续复用了原有的 ThreadScope 模型。
这些 joiner 直接运行在已有的 ThreadScope 里,因此可以自然继承:
- deadline
- failure policy
- retry
- scheduler
- hook
- metrics
- cancellation
这一点很关键。
高阶编排没有变成另一套独立语义,而是继续放在原有 scope 模型里。这样业务在使用 firstSuccess、quorum、hedged 时,不需要再理解一套新的生命周期和失败处理规则。
增加了 example 示例
之前只提供了 API 文档,肯定是不够的。
很多人真正关心的是:
- 这个库在真实业务里应该怎么组织代码
- 什么时候适合使用
- 典型使用模式长什么样
所以 1.2.0 增加了 examples/ 目录,提供了可以直接运行的示例。
目前包含 4 类例子:
ParallelAggregationExampleFirstSuccessFallbackExampleQuorumVoteExampleChannelPipelineExample
这些示例更接近真实接入场景,可以看作一组最小使用套路,而不只是 API demo。
比如并发聚合:
try (ThreadScope scope = ThreadScope.open()
.withFailurePolicy(FailurePolicy.FAIL_FAST)
.withDeadline(Duration.ofSeconds(2))) {
Task<String> profile = scope.submit("load-profile", () -> loadProfile());
Task<Integer> orders = scope.submit("load-orders", () -> loadOrders());
scope.await(profile, orders);
return profile.await() + ", orders=" + orders.await();
}
这类例子对第一次接入的人会更有帮助,能最直观的了解到 ThreadForge 在业务代码里的写法。
增加了 benchmarks
1.2.0 增加了 benchmarks/,基于 JMH 提供了两组基准测试:
FanOutAggregationBenchmarkFirstSuccessBenchmark
对比对象是 Java 里常见的两套原生写法:
ExecutorServiceCompletableFuture
这一步的意义在于提供一个可以复现的性能对比起点。
后续如果继续增加更多场景,就可以更客观地观察 ThreadForge 的 API 抽象带来了多少额外开销,以及换来了多少结构化收益。
观测能力更完整了
ThreadForge 之前已经具备了一些基础观测能力:
ThreadHookTaskInfoScopeMetricsSnapshot- OpenTelemetry hook
这些能力可以满足基础观测需求。1.2.0 又继续补了三块能力,让观测更容易落到工程实践里。
1. SlowTaskHook
现在可以直接对慢任务做统一检测,不需要每个业务场景都自己补阈值判断。
ThreadHook hook = SlowTaskHook.create(Duration.ofMillis(200), event -> {
System.out.println("slow task: " + event.info().name());
});
这对 RPC 聚合、批处理、外部依赖调用都很实用。
2. ThreadHook.andThen(...)
ThreadHook.andThen(...) 支持直接组合多个 hook。
ThreadHook combined = hookA.andThen(hookB);
这样你就可以把:
- tracing
- metrics
- slow-task warning
- 自定义日志
拆成多个独立 hook,再按需组合,而不是把所有逻辑都放进一个实现里。
这个版本适合谁
如果你有下面这些需求,1.2.0 已经比较值得一试:
- 你经常在 Java 里写并发聚合逻辑
- 你希望超时、取消、失败传播这些逻辑能统一管理
- 你不想继续手写大量
CompletableFuture编排 - 你需要 first-success / quorum / hedged 这类更高阶的结果处理模式
- 你希望并发库本身带一些可观测能力,而不是完全依赖业务层补齐
如果你现在更需要的是:
- Spring Boot starter
- Actuator endpoint
- 更完整的框架级自动配置
那还需要等后续版本继续补齐。
结尾
ThreadForge 1.2.0 已发布到 Maven Central:
<dependency>
<groupId>pub.lighting</groupId>
<artifactId>threadforge-core</artifactId>
<version>1.2.0</version>
</dependency>
项目地址:
- GitHub: github.com/wuuJiawei/T…
- Maven Central: central.sonatype.com/artifact/pu…
如果你最近正在处理越来越难维护的 Java 并发代码,可以拿它试试。
也欢迎 Star ,你的每一个 Star 都对我非常重要,比个心吧哈哈。
🫶