异步回调

概述

Netty作为一个优秀的异步的事件驱动的框架,实现了一个功能强大的异步回调结构模型。
下面对比看下不同技术对于同一个需求处理的结果。
以烧水泡茶需求为例,烧水和清洗水壶水杯2个线程是可以同时做的。

方式一:Thread.join()

public class ThreadJoin{
    public static final int SLEEP_TIME = 500;


    static class HotWarterThread extends Thread{
        public HotWarterThread(){
            super("烧水线程");
        }

        @Override
        public void run() {
            System.out.println("洗好水壶");
            System.out.println("盛水");
            System.out.println("开火");
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("水开了");
        }
    }

    static class WashThread extends Thread{
        public WashThread(){
            super("清洗线程");
        }

        @Override
        public void run() {
            System.out.println("洗茶壶茶杯");
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("洗好了");
            System.out.println("装茶叶");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        HotWarterThread t1 = new HotWarterThread();
        WashThread t2 = new WashThread();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        Thread.currentThread().setName("主线程");
        System.out.println("泡茶喝");
    }
}
洗好水壶
盛水
开火
洗茶壶茶杯
洗好了
装茶叶
水开了
泡茶喝

join()方式有诸多受限,没有返回值,没有办法告诉主线程结果。主线程阻塞。

方式二:Callable接口

Callable接口比Runnable接口更进一步,可以返回线程执行结果。
在这里插入图片描述
Future接口里提供了一些方法可以获取任务的执行结果
在这里插入图片描述
1、可以通过get()方法获取线程执行结果。如果操作尚未完成,则当前调用线程会阻塞。如果不允许阻塞太长时间或者无限期阻塞,可以通过带超时时间的get方法获取结果。如果到达超时时间仍然没有完成,抛TimeoutException。
2、通过isDone方法判断当前的异步操作是否完成。如果完成,无论成功与否,返回true,否则返回false。
3、通过cancel方法尝试取消异步操作,结果未知。如果操作已经发生,或者其他原因无法取消,取消失败。
Callable接口的call()方法可以获得线程执行结果。
FutureTask继承了Callable、Runnable接口,作为要执行的任务传给线程,承接着桥梁作用。

public class FutureTaskTest {
    public static final int SLEEP_TIME = 500;


    static class HotWarterThread implements Callable<Boolean> {
        @Override
        public Boolean call() throws Exception {
            System.out.println("洗好水壶");
            System.out.println("盛水");
            System.out.println("开火");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                return false;
            }
            System.out.println("水开了");
            return true;
        }
    }

    static class WashThread  implements Callable<Boolean> {
        @Override
        public Boolean call() throws Exception {
            System.out.println("洗茶壶茶杯");
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e) {
                return false;
            }
            System.out.println("洗好了");
            System.out.println("装茶叶");
            return true;
        }
    }

    public static void drinkTea(boolean b1,boolean b2){
        if(b1 && b2){
            System.out.println("开始泡茶喝");
        }else if(!b1){
            System.out.println("烧水失败");
        }else if(!b2){
            System.out.println("清洗失败");
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Callable<Boolean> job1 = new HotWarterThread();
        Callable<Boolean> job2 = new WashThread();
        FutureTask<Boolean> f1 = new FutureTask<>(job1);
        FutureTask<Boolean> f2 = new FutureTask<>(job2);
        Thread t1 = new Thread(f1,"烧水线程");
        Thread t2 = new Thread(f2,"清洗线程");
        t1.start();
        t2.start();
        boolean b1 = f1.get();
        boolean b2 = f1.get();
        drinkTea(b1,b2);
    }
}
洗好水壶
盛水
开火
洗茶壶茶杯
洗好了
装茶叶
水开了
开始泡茶喝

使用JDK5提供的Future接口实现需求也有不足之处:虽然能够获取其他线程的执行结果了,Future.get()方法是阻塞的,不是异步的。

方法三:

Netty自己基于JDK的Future实现了自己的一些异步回调技术。主要的接口有Future(Netty)和GenericFutureListener,用于表示异步执行完成的监听器。
在这里插入图片描述
在Netty中,绝大部分的操作都是异步的。例如客户端连接服务端:

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
        .childOption(ChannelOption.SO_KEEPALIVE, true)
        .option(ChannelOption.SO_BACKLOG, 128)
        .childHandler(new ChatServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(40000).addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
        if (future.isSuccess()) {
            System.out.println("成功");
        } else {
            System.out.println("失败");
            future.cause().printStackTrace();
        }
    }
});

如果服务端启动占用端口失败,会打印失败和堆栈信息:
在这里插入图片描述
Netty提供的Future接口和JDK的Future同名,但是提供了诸多方法,例如
通过 isDone 方法来判断当前操作是否完成;
通过 isSuccess 方法来判断已完成的当前操作是否成功;
通过 getCause 方法来获取已完成的当前操作失败的原因;
通过 isCancelled 方法来判断已完成的当前操作是否被取消;
通过 addListener 方法来注册监听器,当操作已完成(isDone 方法返回完成),将会通知指定的监听器;如果 Future 对象已完成,则通知指定的监听器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值