netty--【NioEventLoopGroup】

NioEventLoopGroup

在这里插入图片描述
开始流水账式分析:

NioEventLoopGroup(自身)

先看看常用的
new NioEventLoopGroup();

NioEventLoopGroup这个类中本身没有去定义任何成员变量

从无参构造方法不断调用,
在这里插入图片描述
无参构造默认传输的线程数是0,创建了一个nullExecutor 继续传递
在这里插入图片描述
其中涉及Java NIO的 selector、netty定义的选择器生成工厂等。
另外再看。

最后到达:

    public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
                             final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory,
                RejectedExecutionHandlers.reject());
    }

MultithreadEventLoopGroup(父类)

super去看父类(抽象类)MultithreadEventLoopGroup

private static final int DEFAULT_EVENT_LOOP_THREADS;

这个类只定义了一个静态成员变量,其值在创始时由静态代码块给予:

    static {
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

        if (logger.isDebugEnabled()) {
            logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
        }
    }

紧接NioEventLoopGroup方法调用的super,到达的是此类中的一个方法:

/**
     * @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor,
     * EventExecutorChooserFactory, Object...)
     */
    protected MultithreadEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
                                     Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, chooserFactory, args);
    }

注意:
NioEventLoopGroup中:
在这里插入图片描述
MultithreadEventLoopGroup中:
在这里插入图片描述

方框中的三个参数:selectorProviderselectStrategyFactory, RejectedExecutionHandlers.reject()
均放在args这个里面传递,后面会用到!

先看一下常量 DEFAULT_EVENT_LOOP_THREADS
在这里插入图片描述
在这里插入图片描述

Runtime.getRuntime().availableProcessors()
//返回当前虚拟机可用核心数

可见 DEFAULT_EVENT_LOOP_THREADS :常量、线程数的默认值、为当前虚拟机可用核心数*2

所以对于

    /**
     * @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)
     */
    protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }

如果没有初始化时没有传线程数/线程数为0,那么默认以虚拟机可用核心数*2作为线程数
如果不为0,则以此为线程数去创建。

MultithreadEventLoopGroup这里也使用了super,还得看其父类MultithreadEventExecutorGroup

MultithreadEventExecutorGroup(父类)

MultithreadEventExecutorGroup定义了五个:

    private final EventExecutor[] children;//这个Group所拥有的执行器数组
    private final Set<EventExecutor> readonlyChildren;//执行器数组的只读Set集合
    private final AtomicInteger terminatedChildren = new AtomicInteger();
    private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
    private final EventExecutorChooserFactory.EventExecutorChooser chooser;//一个由选择器工厂生成出来的选择器

进入到了MultithreadEventExecutorGroup

    /**
     * Create a new instance.
     *
     * @param nThreads          the number of threads that will be used by this instance.
     * @param executor          the Executor to use, or {@code null} if the default should be used.
     * @param args              arguments which will passed to each {@link #newChild(Executor, Object...)} call
     */
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }

接收到线程数量执行器、和args(包含了三个参数传递)
增加了一个DefaultEventExecutorChooserFactory.INSTANCE实例放在参数中
调用其实际的生成线程方法:

/**
     * Create a new instance. 创建了一个实例
     *
     * @param nThreads          the number of threads that will be used by this instance. 	
     * nThreads表示这个实例即将用到的线程数          
     * @param executor          the Executor to use, or {@code null} if the default should be used.
     * executor  如果是默认值的话就应该是null        
     * @param chooserFactory    the {@link EventExecutorChooserFactory} to use.
     * chooserFactory    属于EventExecutorChooserFactory类型
     * 传递的是上面给的DefaultEventExecutorChooserFactory
     * 是因为DefaultEventExecutorChooserFactory这个类实现了EventExecutorChooserFactory接口
     * 
     * @param args              arguments which will passed to each {@link #newChild(Executor, Object...)} call
     */
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        //netty 的ObjectUtil工具类中定义的方法,
        //作用是检查给出的参数是否合格,其实就是判断nThreads这个值
        //要是<=0,则抛出IllegalArgumentException异常
        checkPositive(nThreads, "nThreads");

		//如果传递的executor 为null,也就是NioEventLoopGroup无参传递来的默认值
		//则给它赋值,
        if (executor == null) {
        //给线程执行器内传递了netty定义的线程工厂由它去创建一个线程
        //此时的executor 就是负责启动Reactor的线程(至于为什么?需要看NioEventLoop)
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
//成员变量children 是一个事件执行器数组,此时为根据线程数量定义数组大小
        children = new EventExecutor[nThreads];
//for循环遍历挨个儿创建Executor放进children数组中 
        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                children[i] = newChild(executor, args);//调用实现类(NioEventLoopGroup)创建
                success = true;//是否创建成功的判断
            } catch (Exception e) {
                // TODO: Think about if this is a good exception type
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                if (!success) {//如果没成功
                    for (int j = 0; j < i; j ++) {//优雅地关闭之前创建的所有
                        children[j].shutdownGracefully();
                    }

                    for (int j = 0; j < i; j ++) {
                        EventExecutor e = children[j];
                        try {
                            while (!e.isTerminated()) {
                                e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                            }
                        } catch (InterruptedException interrupted) {
                            // Let the caller handle the interruption.
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            }
        }
//将创建好的所有执行器全都给选择器工厂,选择器工厂加工生成一个选择器
        chooser = chooserFactory.newChooser(children);

		//涉及netty自建的Futrue类需要另外研究
        final FutureListener<Object> terminationListener = new FutureListener<Object>() {
            @Override
            public void operationComplete(Future<Object> future) throws Exception {
                if (terminatedChildren.incrementAndGet() == children.length) {
                    terminationFuture.setSuccess(null);
                }
            }
        };

        for (EventExecutor e: children) {//监听执行器
            e.terminationFuture().addListener(terminationListener);
        }
		//添加执行器组的只读集合
        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

DefaultEventExecutorChooserFactory

netty所提供的默认的 事件执行器选择工厂 类
在这里插入图片描述
通过其定义的DefaultEventExecutorChooserFactory.INSTANCE静态可以直接获取实例
实现了EventExecutorChooserFactory 接口

EventExecutorChooserFactory

EventExecutorChooserFactory 接口定义了事件选择器工厂
事件选择器工厂的作用就是生成一个新的事件选择器
在这里插入图片描述

  1. 声明了创建新的选择器的方法
  2. 声明了选择器

DefaultEventExecutorChooserFactory是EventExecutorChooserFactory 唯一的实现类

  1. DefaultEventExecutorChooserFactory生成何种选择器的规则
    @Override
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {//是则选择	PowerOfTwoEventExecutorChooser选择器
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {//否则选择 GenericEventExecutorChooser选择器
            return new GenericEventExecutorChooser(executors);
        }
    }
//`isPowerOfTwo`判断`执行器的个数`是否是`2的幂次`
    private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;
    }
  1. DefaultEventExecutorChooserFactory定义了两种选择器,每个选择器都具有一个next()方法,在执行器数组中以特定方式选取一个执行器返回
//2次幂事件执行器选择器
    private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();//自增
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[idx.getAndIncrement() & executors.length - 1];
        }
    }
//普通事件执行器选择器
    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        // Use a 'long' counter to avoid non-round-robin behaviour at the 32-bit overflow boundary.
        // The 64-bit long solves this by placing the overflow so far into the future, that no system
        // will encounter this in practice.
        private final AtomicLong idx = new AtomicLong();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }

关于DefaultThreadFactory类中的线程工厂方法

//netty提供的默认线程工厂方法
//线程池名称、是否为守护线程、优先级、线程组
public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
        ObjectUtil.checkNotNull(poolName, "poolName");

//优先级不能小于Thread定义的最小值,大于Thread定义的最大值
//否则抛出异常
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                    "priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
        }
//DefaultThreadFactory的成员变量,prefix:前缀 ,也就是平时看到的真正的线程名称 
        prefix = poolName + '-' + poolId.incrementAndGet() + '-';
        this.daemon = daemon;
        this.priority = priority;
        this.threadGroup = threadGroup;
    }

在创建线程的过程中,newChildMultithreadEventExecutorGroup中定义的一个抽象方法:

    /**
     * Create a new EventExecutor which will later then accessible via the {@link #next()}  method. This method will be
     * called for each thread that will serve this {@link MultithreadEventExecutorGroup}.
     * 
     */
    protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;

转了一大圈,还得记住super只是调用父类方法,这个时候我们还在NioEventLoopGroup中呢

重写的newChild

对于NioEventLoopGroup而言,它是MultithreadEventExecutorGroup的子类,并且自己重写了newChild这个方法:

@Override
//上述中,args中存有三个参数
//selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject()
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    //这里0、1、2三个下标直接取
        SelectorProvider selectorProvider = (SelectorProvider) args[0];//
        SelectStrategyFactory selectStrategyFactory = (SelectStrategyFactory) args[1];
        RejectedExecutionHandler rejectedExecutionHandler = (RejectedExecutionHandler) args[2];
        EventLoopTaskQueueFactory taskQueueFactory = null;
        EventLoopTaskQueueFactory tailTaskQueueFactory = null;

        int argsLength = args.length;
        if (argsLength > 3) {
            taskQueueFactory = (EventLoopTaskQueueFactory) args[3];
        }
        if (argsLength > 4) {
            tailTaskQueueFactory = (EventLoopTaskQueueFactory) args[4];
        }
        //NioEventLoopGroup创建的执行器是NioEventLoop
        return new NioEventLoop(this, executor, selectorProvider,
                selectStrategyFactory.newSelectStrategy(),
                rejectedExecutionHandler, taskQueueFactory, tailTaskQueueFactory);
    }

总结:

  • NioEventLoopGroup的无参构造会默认创建i=虚拟机可用核心数*2EventExecutor,若指定了线程数量则按照指定的数量
  • NioEventLoopGroup通过调用inewChild完成i个EventExecutor(NioEventLoop)的创建
  • 在创建完成后还会根据执行器集合生成合适的选择器
    ……未完
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上岸撒尿的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值