前言
前面 分析了Netty整体的流程 和 Channel的结构,我们看到 Netty 中有很多的异步调用,所以在介绍更多 NIO 相关的内容之前,我们来看看它的异步接口是怎么实现的。
回顾
前面我们在介绍 Echo 例子的时候,已经用过了 ChannelFuture 这个接口了,接下来我们就来看看 Netty 中的异步调用是如何实现的。
客户端
// Start the client.
ChannelFuture future = b.connect(HOST, PORT);
future.sync();
// Wait until the connection is closed.
Channel channel= future.channel();
ChannelFuture closeFuture=channel.closeFuture();
closeFuture.sync();
服务端
// Start the server.
ChannelFuture future = b.bind(PORT);
future.sync();
// Wait until the server socket is closed.
Channel channel = future.channel();
ChannelFuture closeFuture = channel.closeFuture();
closeFuture.sync();
特意把代码拆开,方便理解,可以看到 其实客户端和服务端 结构是差不多的,相信分析了Future 结构后,我们对上面的代码理解会更加的深刻。
JDK 中的 Future
关于 Future 接口,常用的就是在使用 Java 的线程池 ThreadPoolExecutor 的时候了。在 submit 一个任务到线程池中的时候,返回的就是一个 Future 实例,通过它来获取提交的任务的执行状态和最终的执行结果。
下面是 JDK 中的 Future 接口 java.util.concurrent.Future
:
public interface Future<V> {
// 取消该任务
boolean cancel(boolean mayInterruptIfRunning);
// 任务是否已取消
boolean isCancelled();
// 任务是否已完成
boolean isDone();
// 阻塞获取任务执行结果
V get() throws InterruptedException, ExecutionException;
// 带超时参数的获取任务执行结果
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Netty 中的 Future 接口继承了 JDK 中的 Future 接口,然后添加了一些方法:
Netty 中的Future
io.netty.util.concurrent.Future
:
public interface Future<V> extends java.util.concurrent.Future<V> {
// 是否成功
boolean isSuccess();
// 是否可取消
boolean isCancellable();
// 如果任务执行失败,这个方法返回异常信息
Throwable cause();
// 添加 Listener 来进行回调
Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
Future<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
// 移除 Listener
Future<V> removeListener(GenericFutureListener<? extends Future<? super V>> listener);
Future<V> removeListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
// 阻塞等待任务结束,如果任务失败,将“导致失败的异常”重新抛出来
Future<V> sync() throws InterruptedException;
// 不响应中断的 sync()
Future<V> syncUninterruptibly();
// 阻塞等待任务结束,和 sync() 功能是一样的,不过如果任务失败,它不会抛出执行过程中的异常
Future<V> await() throws InterruptedException;
Future<V> awaitUninterruptibly();
boolean await(long timeout, TimeUnit unit) throws InterruptedException;
boolean await(long timeoutMillis) throws InterruptedException;
boolean awaitUninterruptibly(long timeout, TimeUnit unit);
boolean awaitUninterruptibly(long timeoutMillis);
// 获取执行结果,不阻塞,如果没数据,返回 NULL。
V getNow();
// 取消任务执行
@Override
boolean cancel(boolean mayInterruptIfRunning);
}
我们可以发现, Netty 的 Future 接口 扩展了 JDK 中 Future 接口,它加了 sync() 和 await() 用于阻塞等待,还加了 Listeners,只要任务结束去回调 Listener 们就可以了。