- Netty 中的Future与JDK中的Future 同名,但是这是两个接口,Netty中的Future继承自JDK中的Future 接口,而Promise又继承自Netty中的Future 接口。
- JDK的Future 功能较弱,只能**同步等待**任务结束(或成功,或失败)才能得到结果
- netty Future 可以实现同步等待任务结束,也可以异步得到结果,但是还是要等待任务结束
- netty promis 不仅有nettyFuture 的功能,而且脱离了任务独立存在,不是被动的只能等待结果,可以作为两个线程间传递结果的容器
| 功能名称 | JdkFuture | NettyFuture | Promise |
|---|---|---|---|
| cancel | 取消任务 | ||
| isCanceled | 任务是否取消 | ||
| isDone | 任务是否完成,不能区分成功与失败 | ||
| get | 获取任务结果,阻塞等待 | ||
| getNow | 获取任务结果,非阻塞,还未产生结果时返回Null | ||
| await | 等待任务结束,如果任务失败,不会抛出异常,而是需要通过isSuccess 判断 | ||
| sync | 等待任务结束,如果任务失败,抛出异常 | ||
| isSuccess | 判断任务是否成功 | ||
| cause | 获取失败信息,非阻塞,如果没有失败,返回null | ||
| addLinstener | 添加回调,异步接收结果 | ||
| setSuccess | 设置结果成功 | ||
| setFailure | 设置结果失败 |
Future 就是在线程间传递结果或者传递数据的一个容器,而这里jdk的Future 是被动的,必须由执行任务的线程填到Future 里面,而不能是主动的向Future 中去填
package d2;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.*;
@Slf4j
public class TestJdkFuture {
@Test
public void test1() throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(2);
Future future = service.submit(new Callable() {
@Override
public Integer call() throws Exception {
log.debug("执行计算");
Thread.sleep(1000);
return 50;
}
});
log.debug("等待结果");
Integer integer = future.get();
log.debug("子线程的计算结果为:{}",integer);
}
}
NettyFuture
@Slf4j
public class TestNettyFuture {
@Test
public void test(){
NioEventLoopGroup eventLoopGroup =new NioEventLoopGroup();
EventLoop eventLoop = eventLoopGroup.next();
Future future = eventLoop.submit(new Callable() {
@Override
public Integer call() throws Exception {
log.debug("执行计算");
return 50;
}
});
future.addListener(new GenericFutureListener>() {
@Override
public void operationComplete(Future super Integer> future) throws Exception {
log.debug("{}",future.getNow());
}
});
}
}
通过addListener 的方式执行future.getNow() 是由执行线程进行的而不是主线程
NettyPromis子线程装入结果:JdkFuture和NettyFuture 中的future 对象并不是主动创建的,而是线程执行时返回的结果
promise 是主动创建的,这和被动创建的future 本身就有本质区别
package d2;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.ExecutionException;
@Slf4j
public class TestNettyPromise {
@Test
public void test() throws ExecutionException, InterruptedException {
NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
EventLoop eventLoop = eventLoopGroup.next();
DefaultPromise promise = new DefaultPromise<>(eventLoop);
new Thread(()->{
log.debug("开始计算");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
promise.setSuccess(50);
},"计算线程").start();
log.debug("等待结果");
System.out.println(promise.get());
}
}
不仅可以填充计算的结果,还可以填充异常
子线程装入异常:package d2;
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.ExecutionException;
@Slf4j
public class TestNettyPromise {
@Test
public void test() throws ExecutionException, InterruptedException {
NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
EventLoop eventLoop = eventLoopGroup.next();
DefaultPromise promise = new DefaultPromise<>(eventLoop);
new Thread(()->{
log.debug("开始计算");
try {
Thread.sleep(1000);
throw new RuntimeException("计算错误!");
} catch (RuntimeException e) {
promise.setFailure(e);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"计算线程").start();
log.debug("等待结果");
try {
log.debug(String.valueOf(promise.get()));
} catch (Exception e){
log.error(e.getMessage());
}
}
}
todo:还是没有感觉到promise 和future 的更大的区别?比如说是否promise 能由主线程传递给子线程值,这里测试之后发现
promise.setSuccess 是希望promise 等于null,也就是不被赋值的,这里不打算深究,留到整体研究源码时再进行研究,这里只做记录。



