io.netty.util.concurrent.DefaultPromise#trySuccess 和 io.netty.util.concurrent.DefaultPromise#setSuccess 是 Netty 中 DefaultPromise 类的两个方法,用于设置异步操作(Promise)的成功结果。两者都属于 Promise 接口的实现,用于通知异步操作完成并设置结果,但它们在行为、语义和使用场景上有关键区别。
1. 方法定义
1.1 trySuccess
- 包:
io.netty.util.concurrent - 类:
io.netty.util.concurrent.DefaultPromise - 方法签名:
boolean trySuccess(V result); - 返回值:
boolean(true表示成功设置结果,false表示设置失败) - 描述:尝试将
Promise设置为成功状态并存储结果。如果Promise尚未完成(即result字段为null),则设置成功并返回true;如果已完成(成功或失败),则返回false,不修改状态。
1.2 setSuccess
- 包:
io.netty.util.concurrent - 类:
io.netty.util.concurrent.DefaultPromise - 方法签名:
Promise<V> setSuccess(V result); - 返回值:
Promise<V>(返回this,支持链式调用) - 描述:将
Promise设置为成功状态并存储结果。如果Promise尚未完成,设置成功并返回this;如果已完成,抛出IllegalStateException。
2. 源码分析与注释
2.1 trySuccess 源码
以下是 DefaultPromise#trySuccess 的源码
源码注释:
/**
* 尝试将 Promise 设置为成功状态并存储结果。
* 如果 Promise 尚未完成(result == null),设置成功并返回 true。
* 如果 Promise 已完成(成功、失败或取消),返回 false,不修改状态。
* @param result 成功的结果
* @return true 表示设置成功,false 表示设置失败
*/
@Override
public boolean trySuccess(V result) {
if (trySuccessInternal(result)) { // 尝试设置结果
notifyListeners(); // 通知监听器
return true;
}
return false;
}
/**
* 内部方法,执行设置成功结果的逻辑。
* @param result 要设置的结果
* @return true 表示设置成功,false 表示设置失败
*/
private boolean trySuccessInternal(Object result) {
return trySetResult(result, false); // 调用 trySetResult
}
/**
* 尝试设置 Promise 的结果。
* @param result 要设置的结果
* @param wasCancelled 是否为取消操作
* @return true 表示设置成功,false 表示设置失败
*/
private boolean trySetResult(Object result, boolean wasCancelled) {
synchronized (this) { // 确保线程安全
// 检查 Promise 是否已完成(result != null)
// 如果 wasCancelled 为 true,仅允许在 result == CANCELLED 时覆盖
if (this.result != null && (!wasCancelled || this.result != CANCELLED)) {
return false; // 已完成,返回 false
}
this.result = result; // 设置结果
checkNotifyWaiters(); // 检查并唤醒等待线程
return true;
}
}
2.2 setSuccess 源码
以下是 DefaultPromise#setSuccess 的源码:
源码注释:
/**
* 将 Promise 设置为成功状态并存储结果。
* 如果 Promise 尚未完成,设置成功并返回 this。
* 如果 Promise 已完成,抛出 IllegalStateException。
* @param result 成功的结果
* @return 当前 Promise 实例
* @throws IllegalStateException 如果 Promise 已完成
*/
@Override
public Promise<V> setSuccess(V result) {
if (setSuccess0(result)) { // 尝试设置结果
notifyListeners(); // 通知监听器
return this; // 返回 Promise 实例
}
throw new IllegalStateException("complete already: " + this); // 已完成,抛出异常
}
/**
* 内部方法,执行设置成功结果的逻辑。
* @param result 要设置的结果
* @return true 表示设置成功,false 表示设置失败
*/
private boolean setSuccess0(Object result) {
return setResult0(result, false); // 调用 setResult0
}
/**
* 设置 Promise 的结果。
* @param result 要设置的结果
* @param wasCancelled 是否为取消操作
* @return true 表示设置成功,false 表示设置失败
*/
private boolean setResult0(Object result, boolean wasCancelled) {
synchronized (this) { // 确保线程安全
// 检查 Promise 是否已完成
if (this.result != null && (!wasCancelled || this.result != CANCELLED)) {
return false; // 已完成,返回 false
}
this.result = result; // 设置结果
checkNotifyWaiters(); // 检查并唤醒等待线程
return true;
}
}
3. 关键区别
trySuccess 和 setSuccess 的核心区别在于对已完成状态的处理方式和返回值语义。以下是详细对比:
| 特性 | trySuccess | setSuccess |
|---|---|---|
| 返回值 | boolean(true 表示成功,false 表示失败) | Promise<V>(返回 this,支持链式调用) |
| 已完成时的行为 | 返回 false,不抛出异常 | 抛出 IllegalStateException |
| 线程安全 | 使用 synchronized 确保线程安全 | 使用 synchronized 确保线程安全 |
| 通知监听器 | 成功设置时调用 notifyListeners() | 成功设置时调用 notifyListeners() |
| 唤醒等待线程 | 成功设置时调用 checkNotifyWaiters() | 成功设置时调用 checkNotifyWaiters() |
| 使用场景 | 允许多次尝试设置结果,适合竞争性场景 | 确保结果只设置一次,适合确定性场景 |
| 异常处理 | 无异常,失败时静默返回 false | 失败时抛出 IllegalStateException |
3.1 行为差异
-
trySuccess:- 非强制性:尝试设置结果,如果
Promise已完成(result != null),返回false,不会抛出异常。 - 适合在多个线程可能竞争设置结果的场景,例如多个线程尝试完成同一个
Promise。 - 示例:多个异步任务可能同时尝试设置结果,只有一个会成功。
- 非强制性:尝试设置结果,如果
-
setSuccess:- 强制性:要求设置结果必须成功,如果
Promise已完成,抛出IllegalStateException。 - 适合在明确知道
Promise未完成且只应由一个线程设置结果的场景。 - 示例:
AbstractUnsafe#register中使用setSuccess确保注册操作只完成一次。
- 强制性:要求设置结果必须成功,如果
3.2 性能差异
- 开销:两者性能差异微小,都使用
synchronized确保线程安全。 trySuccess更灵活,适合需要检查状态的场景。setSuccess更严格,适合需要确保单一设置的场景,但抛出异常可能增加调用方的错误处理成本。
4. 使用场景
4.1 trySuccess
- 竞争性场景:
- 多个线程可能同时尝试设置
Promise的结果,只有第一个成功的线程生效。 - 示例:多个异步任务处理同一个
Promise,如并发连接尝试。
- 多个线程可能同时尝试设置
- 容错性要求:
- 允许调用方处理设置失败的情况(通过检查
false返回值)。 - 示例:在分布式系统中,多个节点尝试完成同一个异步操作。
- 允许调用方处理设置失败的情况(通过检查
- 代码示例:
DefaultPromise<String> promise = new DefaultPromise<>(eventLoop); // 线程 1 boolean success = promise.trySuccess("Result from thread 1"); System.out.println("Thread 1 success: " + success); // true // 线程 2 success = promise.trySuccess("Result from thread 2"); System.out.println("Thread 2 success: " + success); // false
4.2 setSuccess
- 单一设置场景:
- 确保
Promise只由一个线程设置结果,通常在明确控制流的场景。 - 示例:在
AbstractUnsafe#register中,注册完成后由EventLoop线程设置ChannelPromise成功。
- 确保
- 严格控制:
- 要求
Promise未完成,抛出异常以强制调用方检查状态。 - 示例:Netty 内部操作(如
Channel初始化)确保单一完成。
- 要求
- 代码示例:
DefaultPromise<String> promise = new DefaultPromise<>(eventLoop); promise.setSuccess("Result"); // 成功设置 try { promise.setSuccess("Another result"); // 抛出 IllegalStateException } catch (IllegalStateException e) { System.err.println("Promise already completed: " + e.getMessage()); }
238

被折叠的 条评论
为什么被折叠?



