Netty中trySuccess和setSuccess的区别

io.netty.util.concurrent.DefaultPromise#trySuccessio.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);
    
  • 返回值booleantrue 表示成功设置结果,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. 关键区别

trySuccesssetSuccess 的核心区别在于对已完成状态的处理方式返回值语义。以下是详细对比:

特性trySuccesssetSuccess
返回值booleantrue 表示成功,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());
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值