netty客户端引发的线程血案(三)

本文对比分析了Netty 3.10.5和3.2.4客户端的线程管理,特别是线程池的创建和工作流程。3.10.5版本在初始化时预创建了线程,而3.2.4则在需要时才创建work线程。当socket关闭时,3.2.4能自动关闭相关线程,解决了线程雪崩问题。
摘要由CSDN通过智能技术生成

netty客户端引发的线程血案(三)

前言

前文讲述了netty 3.10.5客户端的实现,我们知道了为什么每次递增一定数量的线程,这个跟客户端的线程池的实现机制有很大关系,本文,我们梳理一下3.2.4的客户端流程,寻找一下3.2.4版本不存在线程雪崩的原因。

netty客户端

我们开始先从引导类ClientBootstrap开始我们的旅程,在实例化ClientBootstrap时,我们需要构建channelFactory,代码见下:

   // Configure the client.
        ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

可以看到构建了2个newCachedThreadPool线程池,分别是boss和work线程池,work线程池的大小为CPU核数*2,初始的时候,线程池中没有线程,这里跟3.10.5有很大区别,3.10.5在初始化的时候,就把需要的boss线程和work线程都启动起来了。
bootstrap.connect(new InetSocketAddress(host, port))中创建channel和3.10.5基本一致,不在详述,重点看一下ChannelState.CONNECTED触发的连接操作,代码:

 private void connect(
            final NioClientSocketChannel channel, final ChannelFuture cf,
            SocketAddress remoteAddress) {
        try {
            if (channel.socket.connect(remoteAddress)) {
                channel.worker.register(channel, cf);
            } else {
            //走此分支
                channel.getCloseFuture().addListener(new ChannelFutureListener() {
                    public void operationComplete(ChannelFuture f)
                            throws Exception {
                        if (!cf.isDone()) {
                            cf.setFailure(new ClosedChannelException());
                        }
                    }
                });
                cf.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                channel.connectFuture = cf;
                //调用boss.register
                boss.register(channel);
            }

        } catch (Throwable t) {
            cf.setFailure(t);
            fireExceptionCaught(channel, t);
            channel.worker.close(channel, succeededFuture(channel));
        }
    }

boss.register(channel)用来创建select,将select注册到channel上,然后select监听key,监听到事件后,按照下面调用流程处理:
processSelectedKeys(selector.selectedKeys())-> connect(k)->ch.worker.register(ch, ch.connectFuture)
在register中会创建select,创建一个work线程放到线程池中,然后启动线程,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值