Netty从0到1系列之ChannelFuture


推荐阅读:

【01】Netty从0到1系列之I/O模型
【02】Netty从0到1系列之NIO
【03】Netty从0到1系列之Selector
【04】Netty从0到1系列之Channel
【05】Netty从0到1系列之Buffer(上)
【06】Netty从0到1系列之Buffer(下)
【07】Netty从0到1系列之零拷贝技术
【08】Netty从0到1系列之整体架构、入门程序
【09】Netty从0到1系列之EventLoop
【10】Netty从0到1系列之EventLoopGroup
【11】Netty从0到1系列之Future
【12】Netty从0到1系列之Promise
【13】Netty从0到1系列之Netty Channel


一、ChannelFuture

1.1 ChannelFuture是啥?

ChannelFuture 是 Netty 框架中异步编程模型的核心组件,它代表了一个尚未完成的 I/O 操作的结果承诺(Promise)。你可以将其理解为一封“未来信使”——当你发起一个网络操作(如连接、写数据),Netty 立即返回一个 ChannelFuture,它承诺在未来某个时刻告诉你操作是否成功, 而不是阻塞等待操作完成。

ChannelFuture 的核心特性:

  • 异步结果表示:代表一个尚未完成的异步操作结果
  • 状态查询:可以检查操作是否完成、成功或失败
  • 完成通知:支持添加监听器在操作完成时接收回调
  • 链式操作:支持将多个异步操作组合成链式调用

核心职责

ChannelFuture 核心职责
表示异步操作的执行状态
提供获取操作结果的接口
支持注册监听器处理操作完成事件
关联对应的Channel
提供同步等待操作完成的方法

在 Netty 中,所有 I/O 操作都是异步的,不会立即返回结果,而是通过 ChannelFuture 来跟踪:

用户代码 Channel ChannelFuture 操作系统 发起异步操作(write/connect等) 提交I/O请求 返回ChannelFuture I/O操作完成 更新状态和结果 通知监听器或唤醒等待线程 用户代码 Channel ChannelFuture 操作系统

1.2 ChannelFuture的继承体系与核心方法

Future<V>
    -> ChannelFuture
        -> DefaultChannelFuture (主要实现)
        -> SucceededChannelFuture (表示已成功的操作)
        -> FailedChannelFuture (表示已失败的操作)
public interface ChannelFuture extends Future<Void> {
    // 获取关联的 Channel
    Channel channel();

    // 是否操作成功
    boolean isSuccess();

    // 是否可取消
    boolean isCancellable();

    // 获取失败原因
    Throwable cause();

    // 添加监听器(核心!)
    ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener);

    // 阻塞等待操作完成(不推荐)
    ChannelFuture sync() throws InterruptedException;
    ChannelFuture await() throws InterruptedException;
}

继承关系图:

Future
Promise
ChannelFuture
DefaultChannelPromise
DefaultPromise
SucceededChannelFuture
FailedChannelFuture

关键实现

  • DefaultChannelPromise:最常用的可写 ChannelFuture
  • SucceededChannelFuture:立即成功的 Future
  • FailedChannelFuture:立即失败的 Future

状态图:

获取结果
处理异常
操作中止
创建ChannelFuture
操作成功完成
操作失败
操作被取消
UNCOMPLETED
开始I/O操作
操作进行中
OPERATION_STARTED
OPERATION_PROGRESS
SUCCESS
FAILED
CANCELLED
发起异步操作
返回 ChannelFuture
操作执行中
操作完成?
通知监听器
调用 addListener()
执行回调逻辑

🌟 核心职责

  • 表示一个未完成的 I/O 操作
  • 提供异步结果通知机制
  • 支持添加多个监听器(Listener)
  • 可阻塞等待结果(不推荐)
  • 实现“无回调地狱”的异步编程

1.3 ChannelFuture的核心API语法

1.3.1 基础ChannelFuture使用

package cn.tcmeta.demo05;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.concurrent.TimeUnit;

/**
 * @author: laoren
 * @description: ChannelFuture 的基本用法
 * @version: 1.0.0
 */
public class BasicChannelFutureExample {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            // 简单的处理器
                        }
                    });

            // 1. 异步连接操作, 返回ChannelFuture
            ChannelFuture connectFuture = bootstrap.connect("127.0.0.1", 8888);
            System.out.println("连接操作已经发起,但是尚未完成连接~~~");

            // 2. 检查状态操作
            System.out.println("连接是否完成: " + connectFuture.isDone());
            System.out.println("连接是否成功: " + connectFuture.isSuccess());
            System.out.println("连接是否取消: " + connectFuture.isCancelled());

            // 3. 同步等待完成, 会阻塞当前线程
            connectFuture.sync();
            System.out.println("连接已经完成 ~~~ ");

            // 4. 获取结果
            Channel channel = connectFuture.channel();
            System.out.println("获取连接通道: " + channel);

            // 5. 异步写入操作
            ChannelFuture writeFuture = channel.writeAndFlush("Hello Netty Server!");

            // 6. 等待写入操作完成,这里设置了最多的等待时间周期, 最多等待2秒
            writeFuture.await(2, TimeUnit.SECONDS);
            if(writeFuture.isDone() && !writeFuture.isSuccess()){
                System.out.println("写入操作失败: " + writeFuture.cause());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}

1.3.2 使用监听器处理异步结果

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

public class ChannelFutureListenerExample {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                     .channel(NioSocketChannel.class)
                     .handler(new SimpleChannelInboundHandler<Object>() {
                         @Override
                         protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
                             // 处理读取到的消息
                         }
                     });
            
            // 1. 发起连接并添加监听器
            ChannelFuture connectFuture = bootstrap.connect("localhost", 8080);
            
            // 2. 使用匿名类添加监听器
            connectFuture.addListener(new GenericFutureListener<ChannelFuture>() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        System.out.println("连接成功!");
                        Channel channel = future.channel();
                        channel.writeAndFlush("Hello");
                    } else {
                        System.err.println("连接失败: " + future.cause().getMessage());
                    }
                }
            });
            
            // 3. 使用lambda表达式添加监听器(Java 8+)
            connectFuture.addListener((ChannelFuture future) -> {
                if (future.isSuccess()) {
                    System.out.println("Lambda: 连接成功!");
                } else {
                    System.err.println("Lambda: 连接失败 - " + future.cause().getMessage());
                }
            });
            
            // 4. 添加多个监听器
            connectFuture.addListener(future -> {
                System.out.println("第一个监听器完成");
            }).addListener(future -> {
                System.out.println("第二个监听器完成");
            });
            
            // 等待连接操作完成
            connectFuture.sync();
            
            // 5. 添加操作完成后的监听器(如果操作已完成会立即通知)
            Channel channel = connectFuture.channel();
            ChannelFuture writeFuture = channel.writeAndFlush("Test Message");
            
            writeFuture.addListener(future -> {
                if (future.isSuccess()) {
                    System.out.println("消息发送成功");
                } else {
                    System.err.println("消息发送失败: " + future.cause().getMessage());
                    // 可以在这里进行重试等错误处理
                }
            });
            
            // 等待一会儿让异步操作完成
            Thread.sleep(1000);
            
        } finally {
            group.shutdownGracefully();
        }
    }
}

1.3.3 ChannelFuture 的链式操作和组合

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

public class ChainedChannelFutureExample {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                     .channel(NioSocketChannel.class)
                     .handler(new ChannelInitializer<Channel>() {
                         @Override
                         protected void initChannel(Channel ch) throws Exception {
                             // 添加处理器
                         }
                     });
            
            // 1. 链式异步操作
            bootstrap.connect("localhost", 8080).addListener((ChannelFuture connectFuture) -> {
                if (connectFuture.isSuccess()) {
                    System.out.println("连接成功,开始发送数据");
                    Channel channel = connectFuture.channel();
                    
                    // 在连接成功后发送第一条消息
                    ChannelFuture firstWriteFuture = channel.writeAndFlush("First Message");
                    
                    firstWriteFuture.addListener((Future<Void> future) -> {
                        if (future.isSuccess()) {
                            System.out.println("第一条消息发送成功,发送第二条");
                            
                            // 在第一条消息发送成功后发送第二条消息
                            ChannelFuture secondWriteFuture = channel.writeAndFlush("Second Message");
                            
                            secondWriteFuture.addListener((Future<Void> f) -> {
                                if (f.isSuccess()) {
                                    System.out.println("第二条消息发送成功,关闭连接");
                                    
                                    // 在所有操作完成后关闭连接
                                    channel.close();
                                }
                            });
                        }
                    });
                }
            });
            
            // 等待一段时间让异步操作完成
            Thread.sleep(3000);
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}

1.4 ChannelFuture的底层实现原理

1.4.1 ChannelFuture 与 Promise 模式

ChannelFuture 基于 Promise 模式实现,分离了操作的执行和结果的消费:

// 简化的实现原理
public interface ChannelFuture extends Future<Void> {
    // 获取关联的Channel
    Channel channel();
    
    // 添加监听器,操作完成时回调
    ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener);
    
    // 同步等待操作完成
    ChannelFuture sync() throws InterruptedException;
    
    // 异步等待操作完成(不抛出异常)
    ChannelFuture await() throws InterruptedException;
}

// 默认实现的核心逻辑
public class DefaultChannelFuture implements ChannelFuture {
    private final Channel channel;
    private volatile boolean done; // 操作是否完成
    private volatile boolean success; // 操作是否成功
    private Throwable cause; // 失败原因
    private Object listeners; // 监听器列表
    
    // 标记操作成功完成
    public boolean setSuccess() {
        // 设置状态字段
        // 通知所有监听器
        notifyListeners();
        return true;
    }
    
    // 标记操作失败
    public boolean setFailure(Throwable cause) {
        // 设置状态字段和失败原因
        // 通知所有监听器
        notifyListeners();
        return true;
    }
    
    // 监听器模式
    private void notifyListeners() {
        // 遍历所有监听器并调用operationComplete方法
        for (GenericFutureListener listener : listeners) {
            try {
                listener.operationComplete(this);
            } catch (Exception e) {
                // 处理监听器异常
            }
        }
    }
}

✅ 1. 重点内容:

  • ChannelFuture 内部维护一个 GenericFutureListener 列表
  • 当 I/O 操作完成时,遍历并通知所有监听器
  • 线程安全:监听器在 EventLoop 线程中执行
// 伪代码:操作完成时通知监听器
void operationComplete() {
    this.isSuccess = true;
    for (GenericFutureListener l : listeners) {
        l.operationComplete(this); // 回调
    }
}

✅ 2. 不可变性设计

  • ChannelFuture 本身是不可变的(Immutable)
  • 一旦操作完成,结果不可更改
  • 符合“承诺”语义

✅ 3. 与 EventLoop 的协同

  • 所有 ChannelFuture 的监听器在 绑定的 EventLoop 线程 中执行
  • 保证无锁串行化,避免竞态条件
// 示例:监听器在 EventLoop 线程中执行
future.addListener(f -> {
    System.out.println("回调执行线程: " + Thread.currentThread().getName());
    // 此处代码由 Channel 的 EventLoop 线程执行
});

1.4.2 ChannelFuture 的线程安全模型

ChannelFuture 是线程安全的,可以在任何线程中添加监听器或检查状态:

public class ChannelFutureThreadSafetyExample {
    public static void demonstrateThreadSafety(Channel channel) {
        // 在不同线程中操作同一个ChannelFuture是安全的
        ChannelFuture writeFuture = channel.writeAndFlush("Test Message");
        
        // 线程1添加监听器
        new Thread(() -> {
            writeFuture.addListener(future -> {
                System.out.println("线程1: 操作完成 - " + Thread.currentThread().getName());
            });
        }).start();
        
        // 线程2添加另一个监听器
        new Thread(() -> {
            writeFuture.addListener(future -> {
                System.out.println("线程2: 操作完成 - " + Thread.currentThread().getName());
            });
        }).start();
        
        // 线程3检查状态
        new Thread(() -> {
            while (!writeFuture.isDone()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println("线程3: 操作已完成");
        }).start();
        
        // Netty确保所有监听器都在正确的EventLoop线程中执行
        // 即使从外部线程添加监听器,回调也会在Channel所属的EventLoop线程中执行
    }
}

1.5 ChannelFuture使用示例

1.5.1 基础 ChannelFuture 使用(连接操作)

package cn.tcmeta.demo05;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * 演示 ChannelFuture 在 connect 操作中的使用
 */
public class ChannelFutureConnectExample {

    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO));

            // connect() 立即返回 ChannelFuture
            ChannelFuture future = bootstrap.connect("www.baidu.com", 80);

            // 方式1:添加监听器(推荐!)
            future.addListener((ChannelFutureListener) f -> {
                if (f.isSuccess()) {
                    System.out.println("✅ 连接成功!远程地址: " + f.channel().remoteAddress());
                    
                    // 发送 HTTP 请求
                    f.channel().writeAndFlush("GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n");
                    
                    // 关闭连接
                    f.channel().close();
                } else {
                    System.err.println("❌ 连接失败: " + f.cause().getMessage());
                }
            });

            // 方式2:阻塞等待(不推荐,仅用于演示)
            // future.sync(); // 等待连接完成
            // if (future.isSuccess()) {
            //     System.out.println("✅ 连接成功");
            // } else {
            //     System.err.println("❌ 连接失败");
            // }

            // 等待连接关闭
            future.channel().closeFuture().sync();

        } finally {
            group.shutdownGracefully();
        }
    }
}

在这里插入图片描述

1.5.2 写操作的 ChannelFuture(数据发送确认)

package cn.tcmeta.demo05;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 演示 write 操作的 ChannelFuture —— 发送确认
 */
public class ChannelFutureWriteExample {

    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new SimpleChannelInboundHandler<Object>() {
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
                                    System.out.println("📩 收到消息: " + msg);

                                    // 发送响应
                                    String response = "Echo: " + msg.toString();
                                    ChannelFuture writeFuture = ctx.writeAndFlush(
                                            Unpooled.copiedBuffer(response, java.nio.charset.StandardCharsets.UTF_8)
                                    );

                                    // 监听发送结果
                                    writeFuture.addListener((ChannelFutureListener) f -> {
                                        if (f.isSuccess()) {
                                            System.out.println("✅ 响应已成功发送到客户端");
                                        } else {
                                            System.err.println("❌ 发送失败: " + f.cause().getMessage());
                                            // 可在此处重试或关闭连接
                                            f.channel().close();
                                        }
                                    });
                                }
                            });
                        }
                    });

            ChannelFuture bindFuture = bootstrap.bind(8080).sync();
            System.out.println("🚀 服务器启动,监听 8080 端口");

            bindFuture.channel().closeFuture().sync();

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

在这里插入图片描述

客户端发送消息

在这里插入图片描述

1.5.3 组合多个 ChannelFuture(并发操作)

package cn.tcmeta.demo05;

import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.util.concurrent.TimeUnit;

/**
 * 演示如何组合多个 ChannelFuture
 */
public class ChannelFutureCompositeExample {

    public static void main(String[] args) throws Exception {
        // 模拟多个异步操作(如连接多个服务)
        Future<?> future1 = asyncOperation("Service-A", 1000);
        Future<?> future2 = asyncOperation("Service-B", 500);
        Future<?> future3 = asyncOperation("Service-C", 1500);

        // 监听所有操作完成
        Future<?> allFuture = future1.addListener(future -> {
            if (future1.isSuccess() && future2.isSuccess() && future3.isSuccess()) {
                System.out.println("✅ 所有服务初始化成功!");
            } else {
                System.err.println("❌ 有服务初始化失败");
            }
        });

        // 阻塞等待(仅演示)
        allFuture.await(3000, TimeUnit.MILLISECONDS);
        System.out.println("🔚 组合操作完成");

        // 模拟异步操作
        Thread.sleep(2000);
    }

    private static Future<?> asyncOperation(String name, long delay) {
        System.out.println("🔧 开始初始化: " + name);
        
        // 模拟异步操作
        io.netty.util.concurrent.DefaultPromise<Object> promise = 
            new io.netty.util.concurrent.DefaultPromise<>(new NioEventLoopGroup().next());
        
        new Thread(() -> {
            try {
                Thread.sleep(delay);
                if (Math.random() > 0.3) {
                    promise.setSuccess(null);
                    System.out.println("✅ " + name + " 初始化成功");
                } else {
                    promise.setFailure(new RuntimeException("初始化失败"));
                    System.err.println("❌ " + name + " 初始化失败");
                }
            } catch (Exception e) {
                promise.setFailure(e);
            }
        }).start();
        
        return promise;
    }
}
🔧 开始初始化: Service-A
🔧 开始初始化: Service-B
🔧 开始初始化: Service-CService-B 初始化失败
🔚 组合操作完成
❌ Service-A 初始化失败
❌ 有服务初始化失败
✅ Service-C 初始化成功

1.6 ChannelFuture的最佳实践

1.6.1 推荐实践操作

✅ 推荐实践

实践说明
始终使用 addListener()避免阻塞,实现真正的异步
避免 sync()await()除非在启动/关闭阶段
处理失败情况Listener 中检查 isSuccess()
及时关闭资源失败时关闭 Channel
使用 ChannelFuture 组合实现复杂异步流程

1.6.2 常见错误

⚠️ 常见错误

// ❌ 错误:阻塞 EventLoop 线程
ctx.writeAndFlush(msg).sync(); // 会阻塞整个 EventLoop!

// ✅ 正确:异步监听
ctx.writeAndFlush(msg).addListener(f -> {
    if (!f.isSuccess()) {
        System.err.println("发送失败: " + f.cause());
    }
});

1.6.3 最佳实践示例代码

ChannelFuture处理最佳实践

package cn.tcmeta.demo05;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.SucceededFuture;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

public class ChannelFutureBestPractices {
    
    // 1. 使用监听器而不是同步等待(避免阻塞EventLoop线程)
    public static void writeWithListener(Channel channel, String message) {
        ByteBuf buffer = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
        ChannelFuture writeFuture = channel.writeAndFlush(buffer);
        
        writeFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                // 这个回调会在Channel所属的EventLoop线程中执行
                if (future.isSuccess()) {
                    System.out.println("消息发送成功: " + message);
                    // 可以在这里进行下一步操作
                } else {
                    System.err.println("消息发送失败: " + future.cause().getMessage());
                    // 错误处理:重试、记录日志等
                    handleWriteFailure(future, message);
                }
                
                // 无论成功失败,都要释放资源
                buffer.release();
            }
        });
    }
    
    // 2. 带重试机制的写入操作
    public static void writeWithRetry(Channel channel, String message, int maxRetries) {
        writeWithRetryInternal(channel, message, maxRetries, 0);
    }
    
    private static void writeWithRetryInternal(Channel channel, String message, 
                                             int maxRetries, int attempt) {
        ByteBuf buffer = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
        ChannelFuture writeFuture = channel.writeAndFlush(buffer);
        
        writeFuture.addListener(future -> {
            if (future.isSuccess()) {
                System.out.println("消息发送成功(尝试 " + (attempt + 1) + "): " + message);
                buffer.release();
            } else if (attempt < maxRetries) {
                System.err.println("发送失败,准备重试 (" + (attempt + 1) + "/" + maxRetries + ")");
                buffer.release();
                
                // 延迟后重试
                channel.eventLoop().schedule(() -> {
                    writeWithRetryInternal(channel, message, maxRetries, attempt + 1);
                }, 1, TimeUnit.SECONDS); // 1秒后重试
            } else {
                System.err.println("消息发送失败,已达最大重试次数: " + message);
                buffer.release();
                handleWriteFailure((ChannelFuture) future, message);
            }
        });
    }
    
    // 3. 组合多个异步操作
    public static void executeSequentialOperations(Channel channel) {
        // 第一步:连接操作(如果是已连接的Channel,这步可以跳过)
        ChannelFuture connectFuture = channel.connect(new InetSocketAddress("127.0.0.1", 8888));

        connectFuture.addListener(connectResult -> {
            if (connectResult.isSuccess()) {
                // 第二步:连接成功后发送认证消息
                ChannelFuture authFuture = channel.writeAndFlush("AUTH token");
                
                authFuture.addListener(authResult -> {
                    if (authResult.isSuccess()) {
                        // 第三步:认证成功后发送实际数据
                        channel.writeAndFlush("Real data").addListener(dataResult -> {
                            if (dataResult.isSuccess()) {
                                System.out.println("所有操作完成成功");
                            } else {
                                System.err.println("数据发送失败: " + dataResult.cause().getMessage());
                            }
                        });
                    } else {
                        System.err.println("认证失败: " + authResult.cause().getMessage());
                    }
                });
            } else {
                System.err.println("连接失败: " + connectResult.cause().getMessage());
            }
        });
    }
    
    private static void handleWriteFailure(ChannelFuture future, String message) {
        // 记录日志、通知监控系统等
        System.err.println("处理发送失败的消息: " + message);
        System.err.println("失败原因: " + future.cause().getMessage());
    }
}

1.6.4 超时处理和错误恢复

package cn.tcmeta.demo05;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutAndRecoveryExample {
    
    // 1. ✅✅✅ 带超时控制的异步操作
    public static void executeWithTimeout(Channel channel, String message, long timeout, TimeUnit unit) {
        ChannelFuture writeFuture = channel.writeAndFlush(message);
        
        // 添加超时监听器
        channel.eventLoop().schedule(() -> {
            if (!writeFuture.isDone()) {
                System.err.println("操作超时,取消操作");
                // 取消操作(如果支持取消)
                writeFuture.cancel(false);
                
                // 执行超时恢复逻辑
                handleTimeout(channel, message);
            }
        }, timeout, unit);
        
        // ✅✅✅ 添加完成监听器
        writeFuture.addListener(future -> {
            if (future.isCancelled()) {
                System.out.println("操作已被取消");
            } else if (future.isSuccess()) {
                System.out.println("操作成功完成");
            } else {
                System.err.println("操作失败: " + future.cause().getMessage());
                handleFailure(channel, message, future.cause());
            }
        });
    }
    
    // 2. ✅✅✅ 复杂的错误恢复策略
    public static void executeWithResilience(Channel channel, String message) {
        ChannelFuture operationFuture = channel.writeAndFlush(message);
        
        operationFuture.addListener((GenericFutureListener<ChannelFuture>) future -> {
            if (future.isSuccess()) {
                handleSuccess(message);
            } else {
                Throwable cause = future.cause();

                if (cause instanceof TimeoutException) {
                    // 超时错误:重试
                    System.err.println("超时,准备重试: " + message);
                    retryOperation(channel, message);
                } else if (isNetworkError(cause)) {
                    // 网络错误:重新连接后重试
                    System.err.println("网络错误,重新连接: " + message);
                    reconnectAndRetry(channel, message);
                } else if (isProtocolError(cause)) {
                    // 协议错误:无法恢复,记录日志
                    System.err.println("协议错误,无法恢复: " + message);
                    logError(message, cause);
                } else {
                    // 其他错误:使用备用方案
                    System.err.println("使用备用方案: " + message);
                    useFallbackStrategy(message);
                }
            }
        });
    }
    
    private static boolean isNetworkError(Throwable cause) {
        // 判断是否为网络错误
        return cause instanceof java.net.ConnectException ||
               cause instanceof java.net.UnknownHostException;
    }
    
    private static boolean isProtocolError(Throwable cause) {
        // 判断是否为协议错误
        return cause instanceof io.netty.handler.codec.DecoderException;
    }
    
    private static void handleTimeout(Channel channel, String message) {
        // 超时处理逻辑
    }
    
    private static void handleFailure(Channel channel, String message, Throwable cause) {
        // 失败处理逻辑
    }
    
    private static void handleSuccess(String message) {
        // 成功处理逻辑
    }
    
    private static void retryOperation(Channel channel, String message) {
        // 重试逻辑
    }
    
    private static void reconnectAndRetry(Channel channel, String message) {
        // 重新连接并重试逻辑
    }
    
    private static void logError(String message, Throwable cause) {
        // 记录错误日志
    }
    
    private static void useFallbackStrategy(String message) {
        // 使用备用方案
    }
}

1.7 ChannelFuture优缺点总结

✅ 优点

优点说明
真正的异步非阻塞提高性能和吞吐量
避免回调地狱通过 Promise 模式链式调用
线程安全监听器在正确线程执行
资源友好不阻塞线程,支持高并发
易于测试可模拟成功/失败场景

❌ 缺点

缺点说明
学习曲线陡峭需理解异步编程模型
调试困难堆栈不连续,日志分散
错误处理复杂需在每个 Listener 中处理异常
过度使用 sync()易导致死锁或性能下降

1.8 总结:ChannelFuture 的核心价值

维度说明
核心思想异步操作的结果承诺 + 非阻塞通知
关键技术监听器模式、事件循环协同、不可变性
性能优势高并发、低延迟、资源高效
设计精髓“不要调用我们,我们会调用你” —— 回调驱动
适用场景所有异步 I/O 操作(connect, write, bind, close)

1.9 一句话总结

💡 一句话总结

ChannelFuture 是 Netty 的“异步信使” —— 它通过 监听器模式事件驱动,将复杂的异步操作转化为清晰的回调逻辑,是实现高性能网络应用的关键设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值