Netty之Future与Promise

07.Netty之Future与Promise

一、概述

Future与Promise在异步处理时,经常用到这两个接口

首先要说明 netty 中的 Future 与 jdk 中的 Future 同名,但是是两个接口,netty 的 Future 继承自 jdk 的 Future,而 Promise 又对 netty Future 进行了扩展

  • jdk Future:只能同步等待任务结束(或成功、或失败)才能得到结果;
  • netty Future:可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束;
  • netty Promise:不仅有 netty Future 的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器
功能/名称jdk Futurenetty FuturePromise
cancel取消任务--
isCanceled任务是否取消--
isDone任务是否完成,不能区分成功失败--
get获取任务结果,阻塞等待--
getNow-获取任务结果,非阻塞,还未产生结果时返回 null-
await-等待任务结束,如果任务失败,不会抛异常,而是通过 isSuccess 判断-
sync-等待任务结束,如果任务失败,抛出异常-
isSuccess-判断任务是否成功-
cause-获取失败信息,非阻塞,如果没有失败,返回null-
addLinstener-添加回调,异步接收结果-
setSuccess--设置成功结果
setFailure--设置失败结果

二、使用

  • 2.1 JDK Future
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class TestJdkFuture {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1.创建线程池
        ExecutorService service = Executors.newFixedThreadPool(2);
        //2.提交任务
        Future<Integer> future = service.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                log.info("执行计算");
                Thread.sleep(5000);
                return 100;
            }
        });

        log.info("等待结果...");
        //主线程通过future获取结果,阻塞等待结果返回
        Integer integer = future.get();
        log.info("result:{}",integer);
    }
}

运行结果

09:11:15.931 [main] INFO com.lilinchao.netty.future.TestJdkFuture - 等待结果...
09:11:16.059 [pool-1-thread-1] INFO com.lilinchao.netty.future.TestJdkFuture - 执行计算
09:11:21.071 [main] INFO com.lilinchao.netty.future.TestJdkFuture - result:100
2.2 Netty Future
import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

@Slf4j
public class TestNettyFuture {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        NioEventLoopGroup group = new NioEventLoopGroup();

        EventLoop eventLoop = group.next();

        Future<Integer> future = eventLoop.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                log.info("计算中...");
                Thread.sleep(5000);
                return 100;
            }
        });

        // 主线程中获取结果
//        System.out.println(Thread.currentThread().getName() + " 获取结果");
//        System.out.println("getNow " + future.getNow());
//        System.out.println("get " + future.get());

        //异步
        future.addListener(new GenericFutureListener<Future<? super Integer>>() {
            @Override
            public void operationComplete(Future<? super Integer> future) throws Exception {
                log.info("result:{}",future.getNow());
            }
        });
    }
}

运行结果

09:14:00.656 [nioEventLoopGroup-2-1] INFO com.lilinchao.netty.future.TestNettyFuture - 计算中...
09:14:05.662 [nioEventLoopGroup-2-1] INFO com.lilinchao.netty.future.TestNettyFuture - result:100

说明

Netty中的Future对象,可以通过EventLoop的sumbit()方法得到

  • 可以通过Future对象的get方法,阻塞地获取返回结果
  • 也可以通过getNow方法,获取结果,若还没有结果,则返回null,该方法是非阻塞的
  • 还可以通过future.addListener方法,在Callable方法执行的线程中,异步获取返回结果
2.3 Netty Promise

Promise相当于一个容器,可以用于存放各个线程中的结果,然后让其他线程去获取该结果

import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutionException;

@Slf4j
public class TestNettyPromise {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //1.准备 EventLoop 对象
        NioEventLoopGroup group = new NioEventLoopGroup();
        EventLoop loop = group.next();

        //2.可以主动创建 promise, 结果容器
        DefaultPromise<Integer> promise = new DefaultPromise<>(loop);

        new Thread(() -> {
            //3.任意一个线程执行计算,计算完毕后向 promise 填充结果
            log.info("开始计算...");
            try {
//                int i = 1 / 0;
                Thread.sleep(5000);
                promise.setSuccess(80);
            } catch (InterruptedException e) {
                e.printStackTrace();
                promise.setFailure(e);
            }
        }).start();

        //4.接收结果的线程
        log.info("waiting...");
        log.info("result:{}",promise.get());
    }
}

运行结果

09:23:53.532 [main] INFO com.lilinchao.netty.future.TestNettyPromise - waiting...
09:23:53.600 [Thread-0] INFO com.lilinchao.netty.future.TestNettyPromise - 开始计算...
09:23:58.612 [main] INFO com.lilinchao.netty.future.TestNettyPromise - result:80
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值