继承关系
io.netty.channel.ChannelFuture extends io.netty.util.concurrent.Future extends java.util.concurrent.Future
java.util.concurrent.Future
JDK1.5新增的接口,Future表示的是一个异步执行的结果。
当一个主线程中存在一个耗时较长的操作时候,可以异步的来处理这个操作,即放在线程池中,主线程继续往下执行,在未来的某个时刻,通过Future来获得这个异步操作的执行结果。
提供如下方法供开发者监控并操作异步执行任务
- boolean cancel(boolean mayInterruptIfRunning);
- boolean isCancelled();
- boolean isDone();
- V get() throws InterruptedException, ExecutionException;
- V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
特别需要注意的是 get() 方法,get()是阻塞的,直到异步任务执行完毕并返回执行结果,V get(long timeout, TimeUnit unit) 会阻塞到指定的timeout时间。
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException;
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws TimeoutException if the wait timed out
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
Future Java Doc使用示例:
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
* made-up.)
* <pre> {@code
* interface ArchiveSearcher { String search(String target); }
* class App {
* ExecutorService executor = ...
* ArchiveSearcher searcher = ...
* void showSearch(final String target)
* throws InterruptedException {
* Future<String> future
* = executor.submit(new Callable<String>() {
* public String call() {
* return searcher.search(target);
* }});
* displayOtherThings(); // do other things while searching
* try {
* displayText(future.get()); // use future
* } catch (ExecutionException ex) { cleanup(); return; }
* }
* }}</pre>
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestFutureTask {
public static void main(String[] args) throws InterruptedException,
ExecutionException {
final ExecutorService exec = Executors.newFixedThreadPool(5);
Callable<String> call = new Callable<String>() {
public String call() throws Exception {
Thread.sleep(1000 * 3);//休眠指定的时间,此处表示该操作比较耗时
return "Other less important but longtime things.";
}
};
Future<String> task = exec.submit(call);
//主线程继续执行
Thread.sleep(1000 * 3);
System.out.println("Let's do important things.");
//获取异步操作的执行结果
String obj = task.get();
System.out.println(obj);
//关闭线程池
exec.shutdown();
}
}
Callable 类似于 Runnable,只不过Callable是有返回值的。
io.netty.util.concurrent.Future
可以理解为升级版的Java Futute,主要升级点在listener(监听器)功能。
可以向Future添加指定的listener,当Future对应的异步任务完成时候,会通知指定的listener,当Future已经是完成状态的时候会立即通知指定的listener。一种典型的观察者模式。
在获取Future返回结果的时候尽量使用listener,不要使用await,await方法是阻塞的,在Netty中是以事件驱动为核心的异步思想。
Netty为什么要拓展Java Future呢?
起始Java Future的设计初衷是极好的,但是存在一个非常尴尬的问题,那就是我们什么时候去调用Future.get()方法获取异步执行结果呢?
我们只是创建了一个异步的任务在主线程外执行,但是!它什么时候执行完成我们是不知道的,也就是说我们调用get()方法去获取异步执行结果的时候会有两种情况:
- 异步执行还没有结束,代码阻塞,等待异步执行结束并返回结果
- 异步执行结束了,直接返回了结果
出现第2种情况我们还能接受,毕竟没有阻塞代码,但是出现第1种情况的时候就非常尴尬了,JDK原生的Future并没有完全解决异步执行的结果获取问题!这样的情况在Netty中肯定是不被接受的,所以就出现了Netty Future中listener的设计。
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.util.concurrent;
import java.util.EventListener;
/**
* Listens to the result of a {@link Future}. The result of the asynchronous operation is notified once this listener
* is added by calling {@link Future#addListener(GenericFutureListener)}.
*/
public interface GenericFutureListener<F extends Future<?>> extends EventListener {
/**
* Invoked when the operation associated with the {@link Future} has been completed.
*
* @param future the source {@link Future} which called this callback
*/
void operationComplete(F future) throws Excep