package io.netty.channel;
import io.netty.bootstrap.Bootstrap;
import io.netty.util.concurrent.BlockingOperationException;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.util.concurrent.TimeUnit;
/**
* The result of an asynchronous {@link Channel} I/O operation.
* 一个异步的针对于Channel的IO操作的结果
*
*
* All I/O operations in Netty are asynchronous. It means any I/O calls will
* return immediately with no guarantee that the requested I/O operation has
* been completed at the end of the call. Instead, you will be returned with
* a {@link ChannelFuture} instance which gives you the information about the
* result or status of the I/O operation.
* 在Netty中,所有的IO操作都是异步的。划重点
* 在这就意味着任何的Io调用都会立刻返回,但是却不保证这个IO操作在调用结束之后是已完成的。
* 相反,你会得到一个ChannelFuture对象,这个对象携带这Io操作的结果或者状态信息。
*
*
* A {@link ChannelFuture} is either uncompleted or completed.
* When an I/O operation begins, a new future object is created. The new future
* is uncompleted initially - it is neither succeeded, failed, nor cancelled
* because the I/O operation is not finished yet. If the I/O operation is
* finished either successfully, with failure, or by cancellation, the future is
* marked as completed with more specific information, such as the cause of the
* failure. Please note that even failure and cancellation belong to the
* completed state.
* ChannelFuture是未完成的或者完成的。。
* 当一个IO操作开始的时候,一个新的Future对象将会被创建。这个新的future是最开始是未完成的,它既不是成功的,失败的,也不是被取消的,
*以为Io操作到目前还没有结束。
*如果这个IO操作完成,不管是成功的,失败的,还是取消操作的,这个future都会被标记为完成,它会携带一些具体的信息,例如失败的原因等等。
*请注意,即使是失败和取消都属于完成的状态。
*下面是示意图
*
* +---------------------------+
* | Completed successfully |
* +---------------------------+
* +----> isDone() = true |
* +--------------------------+ | | isSuccess() = true |
* | Uncompleted | | +===========================+
* +--------------------------+ | | Completed with failure |
* | isDone() = false | | +---------------------------+
* | isSuccess() = false |----+----> isDone() = true |
* | isCancelled() = false | | | cause() = non-null |
* | cause() = null | | +===========================+
* +--------------------------+ | | Completed by cancellation |
* | +---------------------------+
* +----> isDone() = true |
* | isCancelled() = true |
* +---------------------------+
*
*
* Various methods are provided to let you check if the I/O operation has been
* completed, wait for the completion, and retrieve the result of the I/O
* operation. It also allows you to add {@link ChannelFutureListener}s so you
* can get notified when the I/O operation is completed.
* 提供了各种各样的方法让你检查IO操作是否已经完成,等待完成,获取IO操作结果。他也允许你添加ChannelFutureListener,
* 让你能够在IO操作完成之后收到通知
*
* Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}
* 应该使用addListener(GenericFutureListener)这样的方式去获取结果,而不是使用await()方法。
*
* It is recommended to prefer {@link #addListener(GenericFutureListener)} to
* {@link #await()} wherever possible to get notified when an I/O operation is
* done and to do any follow-up tasks.
* 只要IO操作完成,它就推荐使用addListener(GenericFutureListener)来获得通知,然后执行下面的任务。
*
* {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds
* the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and
* I/O thread will notify the listeners when the I/O operation associated with
* the future is done. {@link ChannelFutureListener} yields the best
* performance and resource utilization because it does not block at all, but
* it could be tricky to implement a sequential logic if you are not used to
* event-driven programming.
* addListener(GenericFutureListener)是非阻塞的。可以非常简单的添加到ChannelFuture中,
* 当与这个future相关的Io操作完成之后,IO线程将会通知这些监听器。
* 使用ChannelFutureListener会有最好的性能和资源利用的表现,因为它是完全不阻塞的。
* 但是它对于实现一个顺序逻辑是不太友好的,如果你没有使用过事件驱动编程的话
*
* By contrast, {@link #await()} is a blocking operation. Once called, the
* caller thread blocks until the operation is done. It is easier to implement
* a sequential logic with {@link #await()}, but the caller thread blocks
* unnecessarily until the I/O operation is done and there's relatively
* expensive cost of inter-thread notification. Moreover, there's a chance of
* dead lock in a particular circumstance, which is described below.
* 相比而言,await()是一个阻塞的操作,一旦被调用,这个调用线程将会一直阻塞,知道操作完成。
* 它很容易就能够实现顺序逻辑,但是调用者线程会进行没有必要的阻塞,直到io操作完成,所在在夸线程通信当中,这里会产生相对昂贵的成本。
* 更重要的是,在一个特殊的环境下,会给产生死锁提供一个机会。
*
Do not call {@link #await()} inside {@link ChannelHandler}
* 不要在ChannelHandler中调用await()方法。
* The event handler methods in {@link ChannelHandler} are usually called by
* an I/O thread. If {@link #await()} is called by an event handler
* method, which is called by the I/O thread, the I/O operation it is waiting
* for might never complete because {@link #await()} can block the I/O
* operation it is waiting for, which is a dead lock.
* 在ChannelHandle中的事件处理器方法通常会被一个Io线程所调用,如果await()方法被一个事件处理方法调用,然后这个事件处理方法又被IO线程调用,
* 那么这个IO线程就会一直等待,也许再也不会结束。因为await在等待着Io线程结束,这样就产生了一个死锁
*
* // BAD - NEVER DO THIS
* 坏的写法,永远也不要这么做
* {@code @Override}
* public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
* {@link ChannelFuture} future = ctx.channel().close();
* future.awaitUninterruptibly();//调用了await方法,等待Io线程执行完毕,而io线程却在等待ChannelHandler的事件方法执行完毕,死锁就产生了。
* // Perform post-closure operation
* // ...
* }
*
* // GOOD
* {@code @Override}
* public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
* {@link ChannelFuture} future = ctx.channel().close();
* future.addListener(new {@link ChannelFutureListener}() {
* public void operationComplete({@link ChannelFuture} future) {
* // Perform post-closure operation
* // ...
* }
* });
* }
*
*
* In spite of the disadvantages mentioned above, there are certainly the cases
* where it is more convenient to call {@link #await()}. In such a case, please
* make sure you do not call {@link #await()} in an I/O thread. Otherwise,
* {@link BlockingOperationException} will be raised to prevent a dead lock.
* 如上所述,尽管有这些劣势,但是当然也有一些调用await更加方便的情况,
* 这样的情况下,请确定你没有在一个IO线程中调用await,否则将会抛出异常来阻塞死锁的发生
*
*
Do not confuse I/O timeout and await timeout
* 不要混淆IO超时跟等待超时。
*
* The timeout value you specify with {@link #await(long)},
* {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or
* {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O
* timeout at all. If an I/O operation times out, the future will be marked as
* 'completed with failure,' as depicted in the diagram above. For example,
* connect timeout should be configured via a transport-specific option:
* 等待超时跟io超时完全没有关系。如果一个IO操作超时,这个future将会被用失败标记为完成。就像上面的图描述的那样,
* 例如连接超时时间应该通过一个特定的传输选项进行配置。
*
* // BAD - NEVER DO THIS
* {@link Bootstrap} b = ...;
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly(10, TimeUnit.SECONDS);//等待超时
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* // You might get a NullPointerException here because the future
* // might not be completed yet.
* //在这个地方可能会抛出一个空指针异常,因为这个future还没有被标记为完成。
* f.cause().printStackTrace();
* } else {
* // Connection established successfully
* }
*
* // GOOD
* {@link Bootstrap} b = ...;
* // Configure the connect timeout option.
* b.option({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);
* IO超时中的连接超时
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly();
*
* // Now we are sure the future is completed.
* assert f.isDone();//io超时后,future就会被标记成done了。
*
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* f.cause().printStackTrace();
* } else {
* // Connection established successfully
* }
*
*/
public interface ChannelFuture extends Future {
/**
* Returns a channel where the I/O operation associated with this
* future takes place.
*/
Channel channel();
@Override
ChannelFuture addListener(GenericFutureListener extends Future super Void>> listener);
@Override
ChannelFuture addListeners(GenericFutureListener extends Future super Void>>... listeners);
@Override
ChannelFuture removeListener(GenericFutureListener extends Future super Void>> listener);
@Override
ChannelFuture removeListeners(GenericFutureListener extends Future super Void>>... listeners);
@Override
ChannelFuture sync() throws InterruptedException;
@Override
ChannelFuture syncUninterruptibly();
@Override
ChannelFuture await() throws InterruptedException;
@Override
ChannelFuture awaitUninterruptibly();
/**
* Returns {@code true} if this {@link ChannelFuture} is a void future and so not allow to call any of the
* following methods:
*
* - {@link #addListener(GenericFutureListener)}
* - {@link #addListeners(GenericFutureListener[])}
* - {@link #await()}
* - {@link #await(long, TimeUnit)} ()}
* - {@link #await(long)} ()}
* - {@link #awaitUninterruptibly()}
* - {@link #sync()}
* - {@link #syncUninterruptibly()}
*
*/
boolean isVoid();
}