1. 概述
JDeferred 是一个轻量级 Java 库(也支持 Groovy),专门用于实现异步编程,让你告别样板代码。这个框架的设计灵感来源于 jQuery 的 Promise/Ajax 特性和 Android 的 Deferred Object 模式。
本文将带你深入了解 JDeferred 的核心功能和实用技巧。
2. Maven 依赖
在项目中集成 JDeferred 非常简单,只需在 pom.xml
中添加以下依赖:
<dependency>
<groupId>org.jdeferred</groupId>
<artifactId>jdeferred-core</artifactId>
<version>1.2.6</version>
</dependency>
⚠️ 最新版本请查阅 Maven 中央仓库
3. Promise 核心机制
假设我们需要调用一个可能出错的同步 REST API,并根据返回结果执行不同操作。在 jQuery 中,我们可以这样写:
$.ajax("/GetEmployees")
.done(function() { alert("success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
JDeferred 提供了类似的 Promise
和 Deferred
接口,通过线程无关的钩子机制实现状态驱动的异步流程:
Deferred<String, String, String> deferred = new DeferredObject<>();
Promise<String, String, String> promise = deferred.promise();
promise.done(result -> System.out.println("Job done"))
.fail(rejection -> System.out.println("Job fail"))
.progress(progress -> System.out.println("Job is in progress"))
.always((state, result, rejection) ->
System.out.println("Job execution started"));
deferred.resolve("msg");
deferred.notify("notice");
deferred.reject("oops");
✅ 关键方法说明:
done()
:仅在任务成功完成时触发fail()
:任务执行异常时触发progress()
:任务开始执行时触发always()
:无论任务状态如何都会触发
⚠️ 状态管理注意事项:
- Deferred 对象有三种状态:
PENDING
/REJECTED
/RESOLVED
- 通过
deferred.state()
查询当前状态 - 状态不可逆:一旦变为
RESOLVED
就不能reject
,变为REJECTED
后不能resolve
或notify
- 违反状态规则会抛出
IllegalStateException
4. 结果过滤器
在获取最终结果前,可以使用 DoneFilter
对结果进行预处理:
private static String modifiedMsg;
static String filter(String msg) {
Deferred<String, ?, ?> d = new DeferredObject<>();
Promise<String, ?, ?> p = d.promise();
Promise<String, ?, ?> filtered = p.then((result) -> {
modifiedMsg = "Hello " + result;
});
filtered.done(r -> System.out.println("filtering done"));
d.resolve(msg);
return modifiedMsg;
}
✅ 过滤器特点:
- 线程安全的处理流程
- 支持链式操作
- 原始结果不会被修改
5. 管道处理器
DonePipe
提供更强大的后处理能力,支持基于结果的条件判断和状态转换:
public enum Result {
SUCCESS, FAILURE
};
private static Result status;
public static Result validate(int num) {
Deferred<Integer, ?, ?> d = new DeferredObject<>();
Promise<Integer, ?, ?> p = d.promise();
p.then((DonePipe<Integer, Integer, Exception, Void>) result -> {
public Deferred<Integer, Exception, Void> pipeDone(Integer result) {
if (result < 90) {
return new DeferredObject<Integer, Exception, Void>()
.resolve(result);
} else {
return new DeferredObject<Integer, Exception, Void>()
.reject(new Exception("Unacceptable value"));
}
}).done(r -> status = Result.SUCCESS )
.fail(r -> status = Result.FAILURE );
d.resolve(num);
return status;
}
⚠️ 实际使用时注意:
- 管道处理可以改变后续流程的状态
- 支持异常传播和自定义错误处理
- 适合复杂的业务规则验证场景
6. Deferred 管理器
实际项目中常需处理多个异步任务,DeferredManager
提供统一管理能力:
Deferred<String, String, String> deferred = new DeferredObject<>();
DeferredManager dm = new DefaultDeferredManager();
Promise<String, String, String> p1 = deferred.promise(),
p2 = deferred.promise(),
p3 = deferred.promise();
dm.when(p1, p2, p3)
.done(result -> ... )
.fail(result -> ... );
deferred.resolve("Hello Baeldung");
✅ 高级特性:
- 可绑定自定义线程池:
ExecutorService executor = Executors.newFixedThreadPool(10); DeferredManager dm = new DefaultDeferredManager(executor);
- 直接使用
Callable
简化代码:DeferredManager dm = new DefaultDeferredManager(); dm.when(() -> { // 业务逻辑,抛出异常会中断任务 }).done(result -> ... ) .fail(e -> ... );
7. 线程安全等待
需要等待所有并行任务完成时,有两种安全方式:
方式一:同步等待(需手动同步)
DeferredManager dm = new DefaultDeferredManager();
Deferred<String, String, String> deferred = new DeferredObject<>();
Promise<String, String, String> p1 = deferred.promise();
Promise<String, String, String> p = dm
.when(p1)
.done(result -> ... )
.fail(result -> ... );
synchronized (p) {
while (p.isPending()) {
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
deferred.resolve("Hello Baeldung");
方式二:推荐的安全等待
try {
p.waitSafely();
} catch (InterruptedException e) {
e.printStackTrace();
}
✅ 最佳实践:
- 优先使用
waitSafely()
,无需手动同步 - 避免在回调中执行耗时操作
- 合理设置线程池大小防止资源耗尽
8. Android 集成
在 Android 项目中使用 JDeferred 需添加特定依赖:
APKLIB 构建方式
<dependency>
<groupId>org.jdeferred</groupId>
<artifactId>jdeferred-android</artifactId>
<version>1.2.6</version>
<type>apklib</type>
</dependency>
AAR 构建方式
<dependency>
<groupId>org.jdeferred</groupId>
<artifactId>jdeferred-android-aar</artifactId>
<version>1.2.6</version>
<type>aar</type>
</dependency>
⚠️ Android 特别注意:
- 确保在主线程处理 UI 更新
- 避免内存泄漏(及时清理回调)
- 使用
DeferredManager
管理生命周期
9. 总结
JDeferred 通过简洁的 API 设计,让 Java 异步编程变得优雅高效。核心优势包括:
✅ 主要亮点:
- 类似 jQuery 的链式调用风格
- 强大的状态管理机制
- 灵活的过滤和管道处理
- 完善的多任务协调能力
- 良好的线程安全设计
⚠️ 使用建议:
- 复杂异步流程优先考虑 JDeferred
- 避免过度嵌套回调(回调地狱)
- 合理使用线程池资源
- 注意异常传播和状态一致性
完整示例代码请查阅 GitHub 仓库。