切片Netty-NioEventLoopGroup

本文基于Netty4.x版本

一. 从New一个对象开始

1.NioEventLoopGroup构造

接前文的demo

NioEventLoopGroup parentGroup = new NioEventLoopGroup();

密密麻麻的构造函数,挑一个最全的构造

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

虽然new NioEventLoopGroup()操作很简洁,但是根据上面最全的构造看出,传递了很多参数。
其中默认参数如下:

  • nThreads: 线程数默认0 ,父类MultithreadEventLoopGroup将调整为NettyRuntime.availableProcessors() * 2
  • executor: 线程池默认null,父类MultithreadEventExecutorGroup设置为 new ThreadPerTaskExecutor(newDefaultThreadFactory());
  • SelectorProvider: selector选择器提供服务,不同系统实现不同
  • SelectStrategyFactory: 选择策略工厂
  • RejectedExecutionHandler: 拒绝执行处理器
2.MultithreadEventLoopGroup构造

紧接着super调用父类的MultithreadEventLoopGroup构造,先执行静态代码块。

static {
		// 设置默认线程数,如果未设置系统参数,则取可利用内核数*2;
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
    }

这里的只做了一件事,就是设置DEFAULT_EVENT_LOOP_THREADS 参数。
如果默认传递线程数为0,设置线程数为DEFAULT_EVENT_LOOP_THREADS数值

protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
3.MultithreadEventExecutorGroup构造

沿着调用链,继续调用父类MultithreadEventExecutorGroup的构造,
途中设置了EventExecutorChooserFactory为DefaultEventExecutorChooserFactory.INSTANCE

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        // 省略线程数校验                                    
        ...
		// 默认这里executor为null
        if (executor == null) {
        	// ThreadPerTaskExecutor是一个特殊线程池,启动一个任务,线程工厂则开启一个新线程
        	// 这里使用FastThreadLocalThread进行包裹,这是一个优化点
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        children = new EventExecutor[nThreads];
		
        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
            	// 实例每个NioEventLoop
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                ...
            } finally {
            	// 进行回滚操作,某个实例化异常,关闭已经启动成功的
                ...
            }
        }
		// NioEventLoop选择器
        chooser = chooserFactory.newChooser(children);
		// 设置事件完成监听器
        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);
    }

二. EventExecutorChooserFactory

public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {

   public EventExecutorChooser newChooser(EventExecutor[] executors) {
   	   // 根据线程数是否为2的幂次方
       if (isPowerOfTwo(executors.length)) {
           return new PowerOfTwoEventExecutorChooser(executors);
       } else {
           return new GenericEventExecutorChooser(executors);
       }
   }
   // 判断是否为2的幂
   // 已8为例,原码二进制为 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 
   // -8在java中以二进制是补码形式(原码,转为反码,再转为补码;反码为补码除符号为除反码,补码在反码基础上+1)
   // -8原码: 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
   // -8反码: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0111
   // -8补码: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000
   // 则 8 & -8 结果还是 8;
   private static boolean isPowerOfTwo(int val) {
       return (val & -val) == val;
   }

   private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
   
       public EventExecutor next() {
           return executors[idx.getAndIncrement() & executors.length - 1];
       }
   }

   private static final class GenericEventExecutorChooser implements EventExecutorChooser {

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

这里不管实际化哪个对象,执行next都是取余操作。
但为何要区分
主要是位操作效率更高,毕竟计算机底层还是二进制。

三.NioEventLoop

newChild调用的是子类NioEventLoopGroup的newChild方法

   protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
    }

可以看到newChild是将之前设置的参数,都传入了NioEventLoop。

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        // 父类方法主要设置参数,建立堵塞队列         
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        // 忽略校验逻辑
        ...
        provider = selectorProvider;
        // 这里是一个优化点
        final SelectorTuple selectorTuple = openSelector();
        // 包装过得选择器
        selector = selectorTuple.selector;
        // 原始的选择器
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

跳过NioEventLoop构造中设置参数的操作,主要看下openSelector。

    private SelectorTuple openSelector() {
        final Selector unwrappedSelector;
        try {
        	// 获取原生的selector,
            unwrappedSelector = provider.openSelector();
        } catch (IOException e) {W
            throw new ChannelException("failed to open a new selector", e);
        }
		// 是否禁用优化,默认为false
        if (DISABLE_KEY_SET_OPTIMIZATION) {
         	// 返回非优化的对象
            return new SelectorTuple(unwrappedSelector);
        }
		// 获取SelectorImpl的class对象
        Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                try {
                    return Class.forName(
                            "sun.nio.ch.SelectorImpl",
                            false,
                            PlatformDependent.getSystemClassLoader());
                } catch (Throwable cause) {
                    return cause;
                }
            }
        });
		// 如果获取的SelectorImpl不是类对象或者不是unwrappedSelector的子类
        if (!(maybeSelectorImplClass instanceof Class) ||
            // ensure the current selector implementation is what we can instrument.
            !((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {
            if (maybeSelectorImplClass instanceof Throwable) {
                Throwable t = (Throwable) maybeSelectorImplClass;
                logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t);
            }
            // 返回非优化的对象
            return new SelectorTuple(unwrappedSelector);
        }

        final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
        final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

        Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                try {
                	// 反射取值
                    Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
                    Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
					// jdk9+版本
                    if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
                        long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
                        long publicSelectedKeysFieldOffset =
                                PlatformDependent.objectFieldOffset(publicSelectedKeysField);

                        if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
                        	
                            PlatformDependent.putObject(
                                    unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
                            PlatformDependent.putObject(
                                    unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
                            return null;
                        }
                    }
					// 设置属性可访问
                    Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }
                    // 设置属性可访问
                    cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }
					// 使用SelectedSelectionKeySet替代默认的selectedKeys,publicSelectedKey
					// SelectedSelectionKeySet为数组结构,原对象为set结构
                    selectedKeysField.set(unwrappedSelector, selectedKeySet);
                    publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
                    return null;
                } catch (NoSuchFieldException e) {
                    return e;
                } catch (IllegalAccessException e) {
                    return e;
                }
            }
        });
		// 结果异常则,返回未优化的对象
        if (maybeException instanceof Exception) {
            ...
            return new SelectorTuple(unwrappedSelector);
        }
        selectedKeys = selectedKeySet;
        return new SelectorTuple(unwrappedSelector,
                                 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
    }

这里为何要进行替代默认的属性呢?
主要是数组遍历及新增新元素,效率比map的结构高许多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值