Netty从0到1系列之Future

『Java分布式系统开发:从理论到实践』征文活动 10w+人浏览 218人参与


推荐阅读:

【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


一、Future

Future和Promise说明:

这两个接口都是处理【异步请求】的接口.这里的Future是指netty当中自己定义的future接口. io.netty.util.concurrent.Future, Promise是对netty future接口进行的扩展.

  • jdk future只能同步等待任务结束【成功、或者失败】才能得到结果.
  • netty future可以同步等待任务结束得到结果,也可以异步方式得到结果,但都要等任务结束.
  • netty promise不仅有netty future的功能, 而且脱离了任务独立存在,只作为两个线程间传递结果的容器

1.1 Netty的Future是啥?

Netty Future 是 Netty 异步编程模型的核心组件,它代表一个尚未完成的异步操作的结果。与 JDK 自带的 java.util.concurrent.Future 相比,Netty Future 提供了更强大、更灵活的功能,特别是添加了监听器机制,使得异步操作的结果处理更加优雅和高效。

Netty 的 Future 体系是其高性能异步非阻塞网络编程的核心基石。它基于 Java 原生 Future 接口,进行了深度扩展和优化,构建了一套高效、灵活、线程安全的异步结果通知机制。

Netty Future 的核心特性:

  • 异步结果表示:代表一个尚未完成的异步操作的结果
  • 状态查询:可以检查操作是否完成、成功或失败
  • 完成通知:支持添加监听器在操作完成时接收回调
  • 阻塞等待:支持同步等待操作完成(可选超时)
  • 链式操作:支持将多个异步操作组合成链式调用
Netty Future 核心特性
异步操作状态跟踪
非阻塞结果获取
监听器机制
操作结果缓存
异常处理机制
与EventLoop集成

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

Netty 的 Future 体系比 JDK 更加丰富和灵活:

io.netty.util.concurrent.Future<V>
    -> ChannelFuture (扩展了Channel相关的功能)
        -> ChannelPromise (可写的ChannelFuture)
    
io.netty.util.concurrent.Promise<V>
    -> DefaultPromise (主要实现)

在这里插入图片描述

JDK提供的Future接口

public interface Future<V> {
	// .... 
}

在这里插入图片描述

  • Future接口「FutureTask是其实现类」,定义了操作「异步任务执行的一些方法」,如获取异步任务的执行结果,取消执行任务,判断任务是否被取消,判断任务是否执行完毕.
    • 如主线程让一个子线程去执行任务,子线程在执行过程中可能比较耗时,启动子线程开始执行任务后, 主线程去做其他事情了,忙其它事情或者先执行完, 过了一会才去获取子任务的执行结果或者变更的任务状态.
  • Future可以为主线程开启一个分支任务,专门为主线程处理耗时任务和复杂的业务.
  • 异步任务必须满足三个条件:
    • 线程
    • 有返回值
    • 异步处理

RunnableFuture, 实现了两个接口RunnableFuture,也就是这个接口支持异步操作,这个是由Future接口特性决定的.同时也可以通过Thread类的构造方法,传入一个RunnableFuture的接口类型的参数,用来启动线程.

在这里插入图片描述

public Thread(RunnableFuture<> r)

现在差一个线程的返回值, Callable接口,实现线程的第三种方式.

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

在这里插入图片描述

FutureTask是RunnableFuture的实现类.

public class FutureTask<V> implements RunnableFuture<V> {}

通过此类可以启动线程, 并且该线程支持异步操作.通过分析,它的构造方法如下所示:

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

结论:

可以通过FutureTask完成异步任务.

public class JdkFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建FutureTask
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            try {
                // 等待3s钟
                TimeUnit.MILLISECONDS.sleep(3000);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println( "[" + Thread.currentThread().getName() + "]" +  " ---  \t\t: " +  "jdk future test running!");
           return "JDK Future";
        });

        new Thread(futureTask).start();
        // 这里阻塞住, 等待futureTask执行完毕, 获取返回值.
        System.out.println( "[" + Thread.currentThread().getName() + "]" +  " ---  \t\t: " +  "获取FutureTask的返回值: " + futureTask.get());
        // 主线程会阻塞住
        System.out.println( "[" + Thread.currentThread().getName() + "]" +  " ---  \t\t: " +  "jdk future test start!");
    }
}

在这里插入图片描述

java.util.concurrentFuture.Future优点与缺点:

优点: future结合线程池异步多线程任务配合, 能显著提高程序的执行效率.

同步方式执行任务

public class SyncTaskTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        try {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "执行任务一, 耗时4s~~~");
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "执行任务二, 耗时4s~~~");
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "执行任务三, 耗时4s~~~");
            TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + " ----- " + "代码执行共耗时: " + (end - start) + " 毫秒");
    }

}

在这里插入图片描述

FutureTask + 线程池执行任务:

package com.rj.demo01;

import java.util.concurrent.*;

/**
 * @author laoren
 */
public class JdkFutureExecutorServiceAsyncTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        FutureTask<String> f1 = new FutureTask<>(() -> {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "任务一执行: 耗时4s");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "First Task!";
        });

        FutureTask<String> f2 = new FutureTask<>(() -> {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "任务一执行: 耗时4s");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "First Task!";
        });

        FutureTask<String> f3 = new FutureTask<>(() -> {
            System.out.println("[" + Thread.currentThread().getName() + "]" + " ---  \t\t: " + "任务一执行: 耗时3s");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "First Task!";
        });

        ExecutorService executorService = Executors.newFixedThreadPool(3);
        executorService.submit(f1); // 提交任务
        executorService.submit(f2);
        executorService.submit(f3);

        executorService.shutdown();
        // get方法会阻塞住主线程
        String s = f1.get();
        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + " ----- " + "代码执行共耗时: " + (end - start) + " 毫秒");
    }
}

特别说明: get方法在获取值的时候,会发生阻塞;

  • 如果把get方法放在主线程的后边,则不会有太大影响.
  • 如果把get方法放在主线程任务之前,此时get方法会阻塞主线程执行.
  • get方法容易发生阻塞,一般建议放在程序的最后边,阻塞的含义就是必须等待计算结果返回,否则代码不会继续向下执行.
  • get方法可以指定具体的待时间,在这个时间这内如果有返回值,则可以正常获取,如果没有返回值,则拉倒.

如何解决get获取值的时候,阻塞主线程

  • get放到最后边.
  • 使用isDone方法进行轮询判断, 但是可能会导致cpu空转,浪费cpu性能
while (true){
    if(task.isDone()){
        System.out.println(Thread.currentThread().getName() + " ----- " +  task.get());
    }else{
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " ----- " +  "正在努力处理.....");
    }
}

submit和execute提交任务的区别:

  1. 返回值

    • execute(Runnable command):无返回值。它只是简单地将任务提交给线程池执行,无法得知任务的执行状态和结果。
    • submit(Callable<T> task) 或者submit(Callable<T> task, T result): 【有返回值】,
      • 对于submit(Callable<T> task),它返回一个Future<T>对象,可以通过这个对象来获取任务的执行结果或者检查任务是否完成、是否被取消等状态。
      • 对于submit(Runnable task, T result),它也返回一个Future<T>对象,当任务执行完成后,可以通过这个Future对象获取指定的结果result
  2. 异常处理

    • execute(Runnable command):如果任务在执行过程中抛出异常,那么这个异常会被线程池内部捕获并处理,通常情况下,调用者无法直接获取到这个异常信息(除非通过一些额外的机制,如在任务中设置全局异常处理器)。
    • submit(Callable<T> task)submit(Runnable task, T result):如果任务在执行过程中抛出异常,这个异常会被封装在Future对象中,调用者可以在调用Future.get()方法时获取到这个异常,以便进行进一步的处理。
  3. 使用场景

    • 如果只需要简单地提交一个任务让线程池执行,并且不关心任务的执行结果和状态,也不需要处理任务执行过程中可能抛出的异常,那么可以使用execute()方法。

      ExecutorService executorService = Executors.newFixedThreadPool(10);
      executorService.execute(() -> {
          // 执行一些任务
      });
      
    • 如果需要获取任务的执行结果,或者需要检查任务的执行状态、处理任务执行过程中可能抛出的异常,那么应该使用submit()方法。例如:

      ExecutorService executorService = Executors.newFixedThreadPool(10);
      Future<Integer> future = executorService.submit(() -> {
          // 执行一些任务并返回结果
          return 42;
      });
      try {
          Integer result = future.get();
          System.out.println("任务结果:" + result);
      } catch (InterruptedException | ExecutionException e) {
          e.printStackTrace();
      }
      

总之,submit()方法提供了更多的功能和灵活性,而execute()方法则更加简单直接。在实际使用中,可以根据具体的需求选择合适的方法来提交任务。

jdk提供的Future缺点总结

  • 对于结果的获取不友好
  • 只能通过阻塞或者轮询的方式来获取结果.

Netty中封装的Future接口

在这里插入图片描述

public interface Future<V> extends java.util.concurrent.Future<V> {
	
}

在这里插入图片描述

为了更好地理解 Netty Future 的状态转换和与 JDK Future 的区别,请看下面的对比图:

创建Future
操作成功完成
操作失败
操作被取消
获取结果
处理异常
操作中止
Uncompleted
Success
Failed
Cancelled
Netty Future优势:
1. 监听器机制
2. 更细粒度状态控制
3. 链式操作支持
4. 与Channel集成

Netty Future全景图

JavaFuture
NettyFuture
Promise
ChannelFuture
CloseFuture
DefaultPromise
DefaultChannelPromise
SucceededFuture
FailedFuture

🌟 核心思想

  • “不要调用我,我会调用你” —— 回调驱动的异步编程模型。

1.3 Future 与异步操作的关系

在 Netty 中,几乎所有的 I/O 操作都是异步的,这些操作会立即返回一个 Future 对象:

应用程序 异步操作 Future 结果 发起操作 返回Future 注册监听器/等待结果 执行并产生结果 设置结果 通知监听器/唤醒等待 应用程序 异步操作 Future 结果

1.4 Netty Future 与Java Future对比

特性Java FutureNetty Future
获取结果get() / get(timeout)✅ 支持
监听完成❌ 不支持addListener()
可写性❌ 只读Promise 可写
线程安全部分✅ 完全线程安全
取消操作cancel()✅ 支持
异常获取cause()
链式调用✅ 支持

Netty Future 的优势

  • 更适合高并发、低延迟的网络编程场景。

1.5 Future的核心操作

Netty 的 Future 提供了丰富的方法来检查状态、获取结果和处理完成事件。

1.5.1 状态检查方法

方法描述
isDone()判断操作是否已完成(无论成功、失败或取消)
isSuccess()判断操作是否成功完成
isCancelled()判断操作是否被取消
cause()获取操作失败的原因,成功或未完成时返回 null

1.5.2 同步等待方法

Future 提供了多种同步等待操作完成的方法:

方法描述
sync()阻塞等待操作完成,操作失败时抛出异常
syncUninterruptibly()类似sync(),但不响应中断
await()阻塞等待操作完成,不抛出操作失败的异常
await(long timeout, TimeUnit unit)带超时的await()
awaitUninterruptibly()不响应中断的await()
awaitUninterruptibly(long timeout, TimeUnit unit)带超时且不响应中断的await()

1.6 Netty Future 的核心接口与实现

1.6.1 io.netty.util.concurrent.Future<V>

Netty 的 Future 接口扩展了 java.util.concurrent.Future<V>,并添加了关键能力:

public interface Future<V> extends java.util.concurrent.Future<V>, Comparable<Future<V>> {
    // 是否成功
    boolean isSuccess();
    // 是否可取消
    boolean isCancellable();
    // 获取失败原因
    Throwable cause();
    // 添加监听器(核心!)
    Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
    // 阻塞等待完成
    Future<V> await() throws InterruptedException;
    Future<V> awaitUninterruptibly();
    // 同步等待(阻塞直到成功)
    Future<V> sync() throws InterruptedException;
    Future<V> syncUninterruptibly();
}

1.6.2 io.netty.util.concurrent.Promise<V>

Promise可写的 Future,代表一个可以被设置结果的“承诺”。

public interface Promise<V> extends Future<V> {
    // 设置成功
    Promise<V> setSuccess(V result);

    // 尝试设置成功
    boolean trySuccess(V result);

    // 设置失败
    Promise<V> setFailure(Throwable cause);

    // 尝试设置失败
    boolean tryFailure(Throwable cause);

    // 标记为不可取消
    boolean setUncancellable();
}

🔑 关键区别

  • Future:只读,只能查询状态
  • Promise:可写,可以设置成功/失败

1.7 Netty Future使用示例

1.7.1 基础Future使用【模拟异步计算】

import io.netty.util.concurrent.*;

import java.util.concurrent.TimeUnit;

/**
 * 演示 Netty Future 的基本用法
 */
public class NettyFutureBasicExample {

    public static void main(String[] args) throws Exception {
        // 创建 EventExecutor(类似线程池)
        EventExecutorGroup group = new DefaultEventExecutorGroup(2);

        try {
            // 模拟一个异步任务
            Future<String> future = asyncCompute(group.next());

            // 添加监听器(推荐方式)
            future.addListener((GenericFutureListener<Future<String>>) f -> {
                if (f.isSuccess()) {
                    System.out.println("✅ 计算成功: " + f.get());
                } else {
                    System.err.println("❌ 计算失败: " + f.cause().getMessage());
                }
            });

            // 方式2:阻塞等待
            // String result = future.sync().get();
            // System.out.println("结果: " + result);

            // 等待完成
            future.await(5, TimeUnit.SECONDS);

        } finally {
            group.shutdownGracefully();
        }
    }

    // 模拟异步计算
    private static Future<String> asyncCompute(EventExecutor executor) {
        DefaultPromise<String> promise = new DefaultPromise<>(executor);

        executor.execute(() -> {
            try {
                Thread.sleep(1000); // 模拟耗时操作
                if (Math.random() > 0.3) {
                    promise.setSuccess("Hello Netty Future!");
                } else {
                    promise.setFailure(new RuntimeException("计算失败"));
                }
            } catch (Exception e) {
                promise.setFailure(e);
            }
        });

        return promise;
    }
}

在这里插入图片描述

基础使用Future示例

import io.netty.util.concurrent.DefaultEventExecutor;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class BasicFutureExample {
    public static void main(String[] args) throws Exception {
        // 创建事件执行器
        EventExecutor executor = new DefaultEventExecutor();
        
        // 提交异步任务,返回Future
        Future<Integer> future = executor.submit(() -> {
            System.out.println("开始执行异步任务...");
            // 模拟耗时操作
            Thread.sleep(2000);
            System.out.println("异步任务完成");
            return 42; // 返回结果
        });
        
        System.out.println("任务已提交,是否完成: " + future.isDone());
        
        // 1. 同步阻塞等待结果
        // Integer result = future.get(); // 无限期等待
        Integer result = future.get(3, TimeUnit.SECONDS); // 带超时等待
        System.out.println("同步获取结果: " + result);
        
        // 2. 异步回调方式(推荐)
        Future<Integer> future2 = executor.submit(() -> {
            Thread.sleep(1000);
            return 100;
        });
        
        future2.addListener(f -> {
            if (f.isSuccess()) {
                Integer result2 = (Integer) f.getNow();
                System.out.println("异步获取结果: " + result2);
            } else {
                System.err.println("任务失败: " + f.cause().getMessage());
            }
        });
        
        // 等待异步任务完成
        Thread.sleep(1500);
        executor.shutdownGracefully();
    }
}

1.7.2 Netty Future同步等待

package cn.tcmeta.future;

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

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class FutureSyncExample {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup(1);
        EventLoop eventLoop = group.next();
        
        try {
            // 提交一个耗时任务
            Future<String> future = eventLoop.submit(() -> {
                System.out.println("任务开始执行,将耗时3秒");
                TimeUnit.SECONDS.sleep(3);
                return "任务完成";
            });
            
            // 示例1: 使用await()等待
            System.out.println("使用await()等待...");
            try {
                // 等待最多5秒
                boolean completed = future.await(5, TimeUnit.SECONDS);
                if (completed) {
                    System.out.println("await() - 操作完成,结果: " + 
                                      (future.isSuccess() ? future.get() : "失败"));
                } else {
                    System.out.println("await() - 操作超时");
                }
            } catch (InterruptedException e) {
                System.out.println("await() - 被中断");
                Thread.currentThread().interrupt();
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }

            // 提交第二个任务
            Future<Object> future2 = eventLoop.submit(() -> {
                System.out.println("第二个任务开始执行,将耗时2秒");
                TimeUnit.SECONDS.sleep(2);
                // 模拟失败
                throw new RuntimeException("故意抛出的异常");
            });
            
            // 示例2: 使用sync()等待
            System.out.println("使用sync()等待...");
            try {
                future2.sync();
                System.out.println("sync() - 操作成功完成");
            } catch (InterruptedException e) {
                System.out.println("sync() - 被中断");
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                System.out.println("sync() - 操作失败: " + e.getMessage());
            }
            
            // 示例3: 使用awaitUninterruptibly()
            Future<String> future3 = eventLoop.submit(() -> {
                System.out.println("第三个任务开始执行,将耗时1秒");
                TimeUnit.SECONDS.sleep(1);
                return "第三个任务完成";
            });
            
            System.out.println("使用awaitUninterruptibly()等待...");
            future3.awaitUninterruptibly();
            System.out.println("awaitUninterruptibly() - 操作完成: " + 
                              future3.isSuccess());
            
        } finally {
            group.shutdownGracefully();
        }
    }
}

在这里插入图片描述

1.7.3 监听器机制

Netty 的 Future 最强大的特性之一是支持监听器,允许异步处理操作结果而无需阻塞线程:

package cn.tcmeta.future;

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

import java.util.concurrent.TimeUnit;

/**
 * 监听器机制
 */
public class FutureListenerExample {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup(1);
        EventLoop eventLoop = group.next();
        
        try {
            // 提交任务并添加监听器
            System.out.println("提交任务并添加监听器");
            Future<String> future = eventLoop.submit(() -> {
                System.out.println("任务执行中...");
                TimeUnit.SECONDS.sleep(2);
                // 可以模拟成功或失败
                // return "任务成功完成";
                throw new RuntimeException("任务执行失败");
            });


            // 添加第一个监听器
            future.addListener((GenericFutureListener<? extends Future<? super Object>>) f -> {
                System.out.println("\n监听器1: 操作完成");
                if (f.isSuccess()) {
                    System.out.println("监听器1: 操作成功,结果: " + f.getNow());
                } else {
                    System.out.println("监听器1: 操作失败,原因: " +
                                      f.cause().getMessage());
                }
            });
            
            // 添加第二个监听器
            future.addListener(f -> {
                System.out.println("\n监听器2: 操作完成");
                if (f.isSuccess()) {
                    System.out.println("监听器2: 执行后续操作...");
                } else {
                    System.out.println("监听器2: 执行错误处理...");
                }
            });
            
            // 主线程可以继续执行其他操作
            System.out.println("\n主线程继续执行其他任务...");
            for (int i = 0; i < 5; i++) {
                System.out.println("主线程工作中: " + i);
                TimeUnit.MILLISECONDS.sleep(500);
            }
            
            // 等待所有操作完成
            future.awaitUninterruptibly();
            System.out.println("\n所有操作处理完毕");
            
        } finally {
            group.shutdownGracefully();
        }
    }
}

提交任务并添加监听器
任务执行中...

主线程继续执行其他任务...
主线程工作中: 0
主线程工作中: 1
主线程工作中: 2
主线程工作中: 3

监听器1: 操作完成
监听器1: 操作失败,原因: 任务执行失败

监听器2: 操作完成
监听器2: 执行错误处理...
主线程工作中: 4

所有操作处理完毕

监听器的执行特性:

  • 监听器在对应的 EventLoop 线程中执行
  • 多个监听器按添加顺序执行
  • 如果操作已完成,添加监听器会立即执行

1.7.4 Future 链式调用(组合异步操作)

package cn.tcmeta.future;

import io.netty.util.concurrent.*;

import java.util.concurrent.TimeUnit;

/**
 * 演示 Future 的链式调用
 */
public class FutureChainingExample {

    public static void main(String[] args) throws Exception {
        EventExecutorGroup group = new DefaultEventExecutorGroup(2);

        try {
            Future<String> step1 = asyncStep("Step-1", 500, group.next());
            Future<String> step2 = step1.addListener((GenericFutureListener<Future<String>>) f -> {
                if (f.isSuccess()) {
                    System.out.println("➡️  Step-1 完成,开始 Step-2");
                    // Step-2 依赖 Step-1 的结果
                    asyncStep("Step-2", 300, group.next())
                            .addListener((GenericFutureListener<Future<String>>) f2 -> {
                                if (f2.isSuccess()) {
                                    System.out.println("✅ 流程完成: " + f.get() + " -> " + f2.get());
                                }
                            });
                }
            });

            step1.await(2, TimeUnit.SECONDS);

        } finally {
            group.shutdownGracefully();
        }
    }

    private static Future<String> asyncStep(String name, long delay, EventExecutor executor) {
        DefaultPromise<String> promise = new DefaultPromise<>(executor);
        executor.execute(() -> {
            try {
                Thread.sleep(delay);
                promise.setSuccess(name + "-OK");
            } catch (Exception e) {
                promise.setFailure(e);
            }
        });
        return promise;
    }
}

在这里插入图片描述

1.8 底层实现原理剖析

1.8.1 状态机设计

setSuccess()
setFailure()
cancel()
Unset
Success
Failure
Cancelled
初始状态
  • 一旦状态变更,不可逆
  • 保证“承诺”的不可变性

1.8.2 监听器执行模型

  • 同步通知:状态变更时立即通知监听器
  • EventLoop 线程安全:确保在正确的线程执行回调
  • 异常隔离:监听器异常不影响其他监听器

1.8.3 内存可见性保证

  • 使用 volatile 关键字确保状态和结果的内存可见性
  • 避免 CPU 缓存不一致问题

1.9 最佳实践与常见陷阱

✅ 推荐实践

实践说明
优先使用 addListener()避免阻塞,实现真正的异步
避免在 EventLoop 中阻塞 sync()防止死锁
处理失败情况检查 isSuccess()cause()
使用 Promise 实现自定义异步逻辑如数据库查询、缓存操作

⚠️ 常见错误

// ❌ 错误:在 EventLoop 线程中阻塞
ctx.executor().execute(() -> {
    someFuture.sync(); // ❌ 可能导致死锁
});

// ✅ 正确:使用监听器
someFuture.addListener(f -> {
    // 处理结果
});

future处理的最佳实践

import io.netty.util.concurrent.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class FutureBestPractices {
    
    // 1. 使用监听器而不是阻塞等待(推荐方式)
    public static void processWithListeners(EventExecutor executor) {
        Future<Long> future = executor.submit(() -> {
            Thread.sleep(1000);
            return System.currentTimeMillis();
        });
        
        future.addListener(f -> {
            if (f.isSuccess()) {
                Long result = (Long) f.getNow();
                System.out.println("异步结果: " + result);
                processResult(result);
            } else {
                handleFailure(f.cause());
            }
        });
    }
    
    // 2. 必要的同步等待(带超时)
    public static Long processWithTimeout(EventExecutor executor) {
        Future<Long> future = executor.submit(() -> {
            Thread.sleep(2500);
            return System.currentTimeMillis();
        });
        
        try {
            // 总是使用带超时的get方法
            return future.get(2, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            System.err.println("操作超时,取消任务");
            future.cancel(true); // 中断任务执行
            return null;
        } catch (Exception e) {
            System.err.println("操作失败: " + e.getMessage());
            return null;
        }
    }
    
    // 3. 组合多个Future
    public static void processMultipleFutures(EventExecutor executor) {
        Future<String> future1 = executor.submit(() -> {
            Thread.sleep(500);
            return "结果1";
        });
        
        Future<String> future2 = executor.submit(() -> {
            Thread.sleep(800);
            return "结果2";
        });
        
        // 等待所有Future完成
        Future<?> combinedFuture = executor.newPromise().setSuccess(null);
        combinedFuture.addListener(f -> {
            if (future1.isSuccess() && future2.isSuccess()) {
                String result1 = future1.getNow();
                String result2 = future2.getNow();
                System.out.println("组合结果: " + result1 + ", " + result2);
            }
        });
    }
    
    // 4. 错误处理和重试机制
    public static void processWithRetry(EventExecutor executor, int maxRetries) {
        AtomicInteger attempt = new AtomicInteger(0);
        
        Future<String> future = executor.submit(() -> {
            int currentAttempt = attempt.incrementAndGet();
            if (currentAttempt < maxRetries && Math.random() > 0.7) {
                throw new RuntimeException("模拟失败,尝试: " + currentAttempt);
            }
            return "成功结果,尝试: " + currentAttempt;
        });
        
        future.addListener(f -> {
            if (!f.isSuccess() && attempt.get() < maxRetries) {
                System.out.println("尝试失败,准备重试: " + f.cause().getMessage());
                // 延迟后重试
                executor.schedule(() -> processWithRetry(executor, maxRetries), 
                                1, TimeUnit.SECONDS);
            } else if (f.isSuccess()) {
                System.out.println("最终成功: " + f.getNow());
            } else {
                System.err.println("所有重试尝试都失败了");
            }
        });
    }
    
    private static void processResult(Long result) {
        System.out.println("处理结果: " + result);
    }
    
    private static void handleFailure(Throwable cause) {
        System.err.println("处理失败: " + cause.getMessage());
        // 记录日志、发送警报等
    }
    
    public static void main(String[] args) throws InterruptedException {
        EventExecutor executor = new DefaultEventExecutor();
        
        System.out.println("=== 测试监听器模式 ===");
        processWithListeners(executor);
        
        System.out.println("=== 测试超时控制 ===");
        Long result = processWithTimeout(executor);
        System.out.println("超时测试结果: " + result);
        
        System.out.println("=== 测试重试机制 ===");
        processWithRetry(executor, 3);
        
        Thread.sleep(5000);
        executor.shutdownGracefully();
    }
}

在这里插入图片描述

1.10 Netty Future 体系的优缺点总结

✅ 优点

优点说明
真正的异步非阻塞提高性能和吞吐量
避免回调地狱通过 Promise 模式链式调用
线程安全监听器在正确线程执行
资源友好不阻塞线程,支持高并发
易于扩展可自定义 Future 实现

❌ 缺点

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

1.11 总结:Netty Future 体系的核心价值

维度说明
核心思想异步操作的结果承诺 + 非阻塞通知
关键技术监听器模式、状态机、EventLoop 协同
性能优势高并发、低延迟、资源高效
设计精髓“承诺-完成-通知” 模型
适用场景所有异步 I/O 操作、自定义异步任务

1.12 一句话总结

💡 一句话总结

  • Netty 的 Future 体系是异步编程的“心脏”
    • 它通过 监听器模式可写承诺(Promise)
    • 将复杂的异步操作转化为清晰、可靠、高效的回调逻辑,是构建高性能网络应用的基石
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值