Netty源码阅读笔记 (一) NioEventLoopGroup的创建

直接调用NioEventLoopGroup类中的无参构造:

	public NioEventLoopGroup() {
        this(0);
    }

调用单参构造并传入0:

	public NioEventLoopGroup(int nThreads) {
        this(nThreads, (Executor) null);
    }

调用双参构造:

	public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }

继续调用三参构造,关于调用SelectorProvider.provider()方法创建SelectorProvider的流程在之前Selector启动分析一篇博客中已经分析过了,链接:https://blog.csdn.net/xxy_hl/article/details/98890436

	public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider) {
        this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
    }

关于DefaultSelectStrategyFactory.INSTANCE:

	public final class DefaultSelectStrategyFactory implements SelectStrategyFactory {
    public static final SelectStrategyFactory INSTANCE = new DefaultSelectStrategyFactory();

    private DefaultSelectStrategyFactory() { }

    @Override
    public SelectStrategy newSelectStrategy() {
        return DefaultSelectStrategy.INSTANCE;
    }
}

可以清楚的看到INSTANCE是DefaultSelectStrategyFactory类内的一个静态成员,直接赋值为new DefaultSelectStrategyFactory(),无参构造方法是私有的,通过此方法对实例进行保护。此外还实现了SelectStrategyFactory接口:

public interface SelectStrategy {
    int SELECT = -1;
    int CONTINUE = -2;
    int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception;
}

该接口提供了一个用来产生Select策略的方法,该方法在netty中只有一种默认的实现,在DefaultSelectStrategy类中:

	public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;
    }

可以看到根据传入的hasTasks的Boolean值来确定返回值。
关于IntSupplier:

public interface IntSupplier {
    int get() throws Exception;
}

如果hasTasks为true返回值是IntSupplier接口中get方法的返回值,get方法在EpollEventLoop,KQueueEventLoop和NioEventLoop三个类中都有不同的实现,这里先不详细讨论。
继续调用四参构造:

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

在调用其父类构造方法时传入的最后一个为RejectedExecutionHandlers.reject(),产生了一个拒绝策略:

public interface RejectedExecutionHandler {
    void rejected(Runnable task, SingleThreadEventExecutor executor);
}

	private static final RejectedExecutionHandler REJECT = new RejectedExecutionHandler() {
        @Override
        public void rejected(Runnable task, SingleThreadEventExecutor executor) {
            throw new RejectedExecutionException();
        }
    };
    
	public static RejectedExecutionHandler reject() {
        return REJECT;
    }

可以看到接口中rejected方法的实现仅仅是抛出了异常。

继续调用其父类MultithreadEventLoopGroup的构造方法:

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

Object …objects这种参数定义是在不确定方法参数的情况下的一种多态表现形式。继续调用其父类的构造方法,通过三目运算传入第一个参数,如果判断结果为true,传入DEFAULT_EVENT_LOOP_THREADS:

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);
        }
    }

SystemPropertyUtil.getInt(“io.netty.eventLoopThreads”, NettyRuntime.availableProcessors() * 2)通过键"io.netty.eventLoopThreads"获取系统属性,如果没有设置则返回NettyRuntime.availableProcessors() * 2,最后再与1比较返回较大值。

NettyRuntime.availableProcessors() :

	private static final AvailableProcessorsHolder holder = new AvailableProcessorsHolder();
	
	public static int availableProcessors() {
        return holder.availableProcessors();
    }

	private int availableProcessors;	

	synchronized int availableProcessors() {
            if (this.availableProcessors == 0) {
                final int availableProcessors =
                        SystemPropertyUtil.getInt(
                                "io.netty.availableProcessors",
                                Runtime.getRuntime().availableProcessors());
                setAvailableProcessors(availableProcessors);
            }
            return this.availableProcessors;
        }

跟上面的方法一样,先根据键值 "io.netty.availableProcessors"获取系统属性,如果没有设置系统属性则调用Runtime.getRuntime().availableProcessors()返回处理器的个数。

再看MultithreadEventLoopGroup的父类MultithreadEventExecutorGroup的构造方法:

 	protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
        this(nThreads, threadFactory == null ? null : new ThreadPerTaskExecutor(threadFactory), args);
    }

通过三目运算传入Executor参数,如果threadFactory的值为null则传入null;否则传入
new ThreadPerTaskExecutor(threadFactory):

	private final ThreadFactory threadFactory;

    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory");
        }
        this.threadFactory = threadFactory;
    }

继续调用其构造方法的重载:

	protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }

这里创建了DefaultEventExecutorChooserFactory实例:

public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();

 private DefaultEventExecutorChooserFactory() { }

DefaultEventExecutorChooserFactory类实现了EventExecutorChooserFactory接口:

public interface EventExecutorChooserFactory {

    EventExecutorChooser newChooser(EventExecutor[] executors);

    @UnstableApi
    interface EventExecutorChooser {
        EventExecutor next();
    }
}

newChooser方法的具体实现:

 	public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }

	private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;
    }

isPowerOfTwo用来判断一个数是否是2的整数次方。
如果isPowerOfTwo返回值为true,则返回PowerOfTwoEventExecutorChooser实例:

	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];
        }
    }

否则返回GenericEventExecutorChooser实例:

	private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

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

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

这两个类的区别在于next方法的不同。
回到构造方法,继续调用其构造方法的重载:

	private final EventExecutor[] children;

	protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }

        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }

        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                children[i] = newChild(executor, args);
                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);

        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);
    }

首先是对nThreads的值进行判断,如果nThreads的值小于等于零则抛出异常;
然后对executor进行判断,如果executor为null,则初始化executor:

	private final ThreadFactory threadFactory;

    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory");
        }
        this.threadFactory = threadFactory;
    }

传入的ThreadFactory实例调用了MultithreadEventExecutorGroup类中的newDefaultThreadFactory():

	protected ThreadFactory newDefaultThreadFactory() {
        return new DefaultThreadFactory(getClass());
    }
    
	public final static int NORM_PRIORITY = 5;

	public DefaultThreadFactory(Class<?> poolType) {
        this(poolType, false, Thread.NORM_PRIORITY);
    }

继续调用构造方法:

	public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {
        this(toPoolName(poolType), daemon, priority);
    }

toPoolName方法:

	public static String toPoolName(Class<?> poolType) {
        if (poolType == null) {
            throw new NullPointerException("poolType");
        }

        String poolName = StringUtil.simpleClassName(poolType);
        switch (poolName.length()) {
            case 0:
                return "unknown";
            case 1:
                return poolName.toLowerCase(Locale.US);
            default:
                if (Character.isUpperCase(poolName.charAt(0)) && Character.isLowerCase(poolName.charAt(1))) {
                    return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);
                } else {
                    return poolName;
                }
        }
    }

poolType是通过调用MultithreadEventExecutorGroup类的getClass方法传入的,下面的switch…case算法主要是生成一个String类型的poolName进行返回。

继续看构造方法:

	public DefaultThreadFactory(String poolName, boolean daemon, int priority) {
        this(poolName, daemon, priority, System.getSecurityManager() == null ?
                Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup());
    }

三目运算根据安全管理器是否为null选择传入ThreadGroup,两个结果在默认情况下返回的都是当前线程的线程组。

DefaultThreadFactory最终的构造方法:

	private final String prefix;
    private final boolean daemon;
    private final int priority;
    protected final ThreadGroup threadGroup;


	public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
        if (poolName == null) {
            throw new NullPointerException("poolName");
        }
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                    "priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
        }

        prefix = poolName + '-' + poolId.incrementAndGet() + '-';
        this.daemon = daemon;
        this.priority = priority;
        this.threadGroup = threadGroup;
    }

poolName经过switch…case方法返回之后如果为null则直接抛出异常。
如果优先级小于最低优先级,大于最高优先级则抛出异常。
接下来就是一系列的赋值操作,DefaultThreadFactory实力创建完成。

回到MultithreadEventExecutorGroup的构造方法,创建完executor实例后根据nThreads的大小初始化EventExecutor数组children。紧接着遍历这个数组,调用抽象方newChild给每个元素赋值,newChild方法在NioEventLoopGroup类中的实现:

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

产生了一个NioEventLoop对象:

	NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        if (selectorProvider == null) {
            throw new NullPointerException("selectorProvider");
        }
        if (strategy == null) {
            throw new NullPointerException("selectStrategy");
        }
        provider = selectorProvider;
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

首先调用父类的构造方法:

	protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        tailTasks = newTaskQueue(maxPendingTasks);
    }
 	protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = Math.max(16, maxPendingTasks);
        this.executor = ObjectUtil.checkNotNull(executor, "executor");
        taskQueue = newTaskQueue(this.maxPendingTasks);
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }
	protected AbstractScheduledEventExecutor(EventExecutorGroup parent) {
        super(parent);
    }
	protected AbstractEventExecutor(EventExecutorGroup parent) {
        this.parent = parent;
    }

一直调用父类的构造方法将传入的参数进行赋值。

回到NioEventLoop的构造方法,selectorProvider以及strategy之前已经生成,这里再次检查是否为null,对provider赋值之后调用openSelector方法:

	private SelectorTuple openSelector() {
        final Selector unwrappedSelector;
        try {
            unwrappedSelector = provider.openSelector();
        } catch (IOException e) {
            throw new ChannelException("failed to open a new selector", e);
        }

        if (DISABLE_KEYSET_OPTIMIZATION) {
            return new SelectorTuple(unwrappedSelector);
        }

        final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

        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;
                }
            }
        });

        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;

        Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                try {
                    Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
                    Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

                    Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }
                    cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }

                    selectedKeysField.set(unwrappedSelector, selectedKeySet);
                    publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
                    return null;
                } catch (NoSuchFieldException e) {
                    return e;
                } catch (IllegalAccessException e) {
                    return e;
                }
            }
        });

        if (maybeException instanceof Exception) {
            selectedKeys = null;
            Exception e = (Exception) maybeException;
            logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e);
            return new SelectorTuple(unwrappedSelector);
        }
        selectedKeys = selectedKeySet;
        logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector);
        return new SelectorTuple(unwrappedSelector,
                                 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
    }

通过provider.openSelector方法创建jdk NIO中原生Selector。

接下来根据DISABLE_KEYSET_OPTIMIZATION判断:

	private static final boolean DISABLE_KEYSET_OPTIMIZATION =
            SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false);

如果设置了系统属性,则直接创建SelectorTuple对象并返回:

	SelectorTuple(Selector unwrappedSelector) {
            this.unwrappedSelector = unwrappedSelector;
            this.selector = unwrappedSelector;
        }

否则创建SelectedSelectionKeySet对象:

	SelectionKey[] keys;
    SelectedSelectionKeySet() {
        keys = new SelectionKey[1024];
    }

紧接着在特权模式下获取"sun.nio.ch.SelectorImpl"的实例化对象,然后通过反射机制将SelectorImpl的

protected Set<SelectionKey> selectedKeys = new HashSet();
private Set<SelectionKey> publicSelectedKeys;

两个成员赋值为selectedKeySet;openSelector方法最后新建SelectorTuple对象并返回,调用双参构造:

	SelectorTuple(Selector unwrappedSelector, Selector selector) {
            this.unwrappedSelector = unwrappedSelector;
            this.selector = selector;
        }

传入unwrappedSelector以及 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet)两个实例;SelectedSelectionKeySetSelector的构造方法:

	private final SelectedSelectionKeySet selectionKeys;
    private final Selector delegate;

    SelectedSelectionKeySetSelector(Selector delegate, SelectedSelectionKeySet selectionKeys) {
        this.delegate = delegate;
        this.selectionKeys = selectionKeys;
    }

回到NioEventLoop的构造方法,在openSelector结束之后剩余三步赋值操作。

回到MultithreadEventExecutorGroup的构造方法,如果在调用newChild方法发生异常的情况下,遍历children数组中已经成功赋值的成员,调用shutdownGracefully方法,在AbstractEventExecutor中的实现:

	static final long DEFAULT_SHUTDOWN_QUIET_PERIOD = 2;
    static final long DEFAULT_SHUTDOWN_TIMEOUT = 15;
	public Future<?> shutdownGracefully() {
        return shutdownGracefully(DEFAULT_SHUTDOWN_QUIET_PERIOD, DEFAULT_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS);
    }

继续看SingleThreadEventExecutor中的实现:

	public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
        if (quietPeriod < 0) {
            throw new IllegalArgumentException("quietPeriod: " + quietPeriod + " (expected >= 0)");
        }
        if (timeout < quietPeriod) {
            throw new IllegalArgumentException(
                    "timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
        }
        if (unit == null) {
            throw new NullPointerException("unit");
        }

        if (isShuttingDown()) {
            return terminationFuture();
        }

        boolean inEventLoop = inEventLoop();
        boolean wakeup;
        int oldState;
        for (;;) {
            if (isShuttingDown()) {
                return terminationFuture();
            }
            int newState;
            wakeup = true;
            oldState = state;
            if (inEventLoop) {
                newState = ST_SHUTTING_DOWN;
            } else {
                switch (oldState) {
                    case ST_NOT_STARTED:
                    case ST_STARTED:
                        newState = ST_SHUTTING_DOWN;
                        break;
                    default:
                        newState = oldState;
                        wakeup = false;
                }
            }
            if (STATE_UPDATER.compareAndSet(this, oldState, newState)) {
                break;
            }
        }
        gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
        gracefulShutdownTimeout = unit.toNanos(timeout);

        if (oldState == ST_NOT_STARTED) {
            try {
                doStartThread();
            } catch (Throwable cause) {
                STATE_UPDATER.set(this, ST_TERMINATED);
                terminationFuture.tryFailure(cause);

                if (!(cause instanceof Exception)) {
                    // Also rethrow as it may be an OOME for example
                    PlatformDependent.throwException(cause);
                }
                return terminationFuture;
            }
        }

        if (wakeup) {
            wakeup(inEventLoop);
        }

        return terminationFuture();
    }

看一下isShuttingDown方法:

	private volatile int state = ST_NOT_STARTED;
	private static final int ST_SHUTTING_DOWN = 3;
	public boolean isShuttingDown() {
        return state >= ST_SHUTTING_DOWN;
    }

state的几种状态:

	private static final int ST_NOT_STARTED = 1;
    private static final int ST_STARTED = 2;
    private static final int ST_SHUTTING_DOWN = 3;
    private static final int ST_SHUTDOWN = 4;
    private static final int ST_TERMINATED = 5;

在NioEventLoop创建时初始化为1。
如果isShuttingDown返回值为false,调用inEventLoop:

	public boolean inEventLoop() {
        return inEventLoop(Thread.currentThread());
    }

在SingleThreadEventExecutor类中inEventLoop抽象方法的实现:

	public boolean inEventLoop(Thread thread) {
        return thread == this.thread;
    }

对thread赋值在doStartThread方法中进行,很明显之前并没有调用doStartThread方法。

在循环中,首先还是通过isShuttingDown判断是否被关闭,在switch块中,另newState为ST_SHUTTING_DOWN(3);

通过STATE_UPDATER:

	private static final AtomicIntegerFieldUpdater<SingleThreadEventExecutor> STATE_UPDATER =
            AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state");

调用CAS方法更新state成员。

gracefulShutdownQuietPeriod和gracefulShutdownTimeout分别保存quietPeriod和timeout的纳秒级颗粒度。

如果oldState为ST_NOT_STARTED(1),调用doStartThread方法:

	private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    for (;;) {
                        int oldState = state;
                        if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                            break;
                        }
                    }

                    // Check if confirmShutdown() was called at the end of the loop.
                    if (success && gracefulShutdownStartTime == 0) {
                        logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " +
                                "before run() implementation terminates.");
                    }

                    try {
                        // Run all remaining tasks and shutdown hooks.
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.release();
                            if (!taskQueue.isEmpty()) {
                                logger.warn(
                                        "An event executor terminated with " +
                                                "non-empty task queue (" + taskQueue.size() + ')');
                            }

                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

断言thread为null,接着调用executor的execute,需要传入一个Runnable 对象:

	public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }

        boolean inEventLoop = inEventLoop();
        addTask(task);
        if (!inEventLoop) {
            startThread();
            if (isShutdown() && removeTask(task)) {
                reject();
            }
        }

        if (!addTaskWakesUp && wakesUpForTask(task)) {
            wakeup(inEventLoop);
        }
    }

因此在doStartThread方法中实例化了一个Runnable对象,可以看到在这里经过处理判断后调用了SingleThreadEventExecutor的run方法,这是个抽象方法,具体的实现在NioEventLoop类中:

protected void run() {
        for (;;) {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    case SelectStrategy.SELECT:
                        select(wakenUp.getAndSet(false));
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                        // fall through
                    default:
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100) {
                    try {
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        runAllTasks();
                    }
                } else {
                    final long ioStartTime = System.nanoTime();
                    try {
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        final long ioTime = System.nanoTime() - ioStartTime;
                        runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
            // Always handle shutdown even if the loop processing threw an exception.
            try {
                if (isShuttingDown()) {
                    closeAll();
                    if (confirmShutdown()) {
                        return;
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
        }
    }

首先调用之前准备好的选择策略selectStrategy.calculateStrategy(selectNowSupplier, hasTasks()):

	int SELECT = -1;
	int CONTINUE = -2;
	public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;
    }
	private final IntSupplier selectNowSupplier = new IntSupplier() {
        @Override
        public int get() throws Exception {
            return selectNow();
        }
    };

因此实际上调用的还是selectNow方法:

	int selectNow() throws IOException {
        try {
            return selector.selectNow();
        } finally {
            if (wakenUp.get()) {
                selector.wakeup();
            }
        }
    }

这里调用的都是JDK中的原生方法。

case为-1条件成立,执行this.select(this.wakenUp.getAndSet(false)),其中wakenUp是一个原子化的Boolean,用来表示是需要唤醒Selector的轮询阻塞,初始化是为true,这里通过CAS操作设置为false代表不需要唤醒,后面在select执行完后,又判断wakenUp是否需要唤醒,说明在select中对Selector的阻塞进行了检查,若是需要唤醒,就通过Selector的原生API完成唤醒。

select方法的实现:

	private void select(boolean oldWakenUp) throws IOException {
        Selector selector = this.selector;
        try {
            int selectCnt = 0;
            long currentTimeNanos = System.nanoTime();
            long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos);

            for (;;) {
                long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L;
                if (timeoutMillis <= 0) {
                    if (selectCnt == 0) {
                        selector.selectNow();
                        selectCnt = 1;
                    }
                    break;
                }

                if (hasTasks() && wakenUp.compareAndSet(false, true)) {
                    selector.selectNow();
                    selectCnt = 1;
                    break;
                }

                int selectedKeys = selector.select(timeoutMillis);
                selectCnt ++;

                if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {
                    break;
                }
                if (Thread.interrupted()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Selector.select() returned prematurely because " +
                                "Thread.currentThread().interrupt() was called. Use " +
                                "NioEventLoop.shutdownGracefully() to shutdown the NioEventLoop.");
                    }
                    selectCnt = 1;
                    break;
                }

                long time = System.nanoTime();
                if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) {
                    selectCnt = 1;
                } else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 &&
                        selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) {
                    logger.warn(
                            "Selector.select() returned prematurely {} times in a row; rebuilding Selector {}.",
                            selectCnt, selector);

                    rebuildSelector();
                    selector = this.selector;
                    selector.selectNow();
                    selectCnt = 1;
                    break;
                }

                currentTimeNanos = time;
            }

            if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",
                            selectCnt - 1, selector);
                }
            }
        } catch (CancelledKeyException e) {
            if (logger.isDebugEnabled()) {
                logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?",
                        selector, e);
            }
        }
    }

这个方法虽然看着很长,但核心就是判断这个存放任务的阻塞队列是否还有任务,若是有,就直接调用Selector的selectNow方法获取就绪的文件描述符,若是没有就绪的文件描述符该方法也会立即返回;若是阻塞队列中没有任务,就调用Selector的select(timeout)方法,尝试在超时时间内取获取就绪的文件描述符。

再回到run方法,ioRatio是执行IO操作和执行任务队列的任务用时比率,默认是50。若是ioRatio设置为100,就必须等到tasks阻塞队列中的所有任务执行完毕才再次进行轮询;若是小于100,那么就根据(100 - ioRatio) / ioRatio的比值乘以ioTime计算出的超时时间让所有任务尝试在超时时间内执行完毕,若是到达超时时间还没执行完毕,就在下一轮的轮询中执行。
processSelectedKeys就是处理轮询的结果集:

	private void processSelectedKeys() {
        if (selectedKeys != null) {
            processSelectedKeysOptimized();
        } else {
            processSelectedKeysPlain(selector.selectedKeys());
        }
    }

selectedKeys不为null,调用processSelectedKeysOptimized方法:

	private void processSelectedKeysOptimized() {
        for (int i = 0; i < selectedKeys.size; ++i) {
            final SelectionKey k = selectedKeys.keys[i];
            // null out entry in the array to allow to have it GC'ed once the Channel close
            // See https://github.com/netty/netty/issues/2363
            selectedKeys.keys[i] = null;

            final Object a = k.attachment();

            if (a instanceof AbstractNioChannel) {
                processSelectedKey(k, (AbstractNioChannel) a);
            } else {
                @SuppressWarnings("unchecked")
                NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
                processSelectedKey(k, task);
            }

            if (needsToSelectAgain) {
                // null out entries in the array to allow to have it GC'ed once the Channel close
                // See https://github.com/netty/netty/issues/2363
                selectedKeys.reset(i + 1);

                selectAgain();
                i = -1;
            }
        }
    }

遍历数组经行处理并将数组中即将处理的元素赋值为null,根据附件attachment判断不同的Channel类型执行不同的processSelectedKey方法。

private void processSelectedKey(SelectionKey k, AbstractNioChannel ch)方法:

	private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
                return;
            }
            if (eventLoop != this || eventLoop == null) {
                return;
            }
            unsafe.close(unsafe.voidPromise());
            return;
        }

        try {
            int readyOps = k.readyOps();
            if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
                int ops = k.interestOps();
                ops &= ~SelectionKey.OP_CONNECT;
                k.interestOps(ops);

                unsafe.finishConnect();
            }

            if ((readyOps & SelectionKey.OP_WRITE) != 0) {
                ch.unsafe().forceFlush();
            }

            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
            }
        } catch (CancelledKeyException ignored) {
            unsafe.close(unsafe.voidPromise());
        }
    }

根据k.readyOps()方法的返回值来判断处理不同的就绪事件。具体的事件处理这里先不分析。

processSelectedKey(SelectionKey k, NioTask task)方法需要使用者实现NioTask接口。

回到processSelectedKeys方法,在selectedKeys为null时,调用processSelectedKeysPlain方法,传入selector.selectedKeys():

private void processSelectedKeysPlain(Set<SelectionKey> selectedKeys) {
        if (selectedKeys.isEmpty()) {
            return;
        }

        Iterator<SelectionKey> i = selectedKeys.iterator();
        for (;;) {
            final SelectionKey k = i.next();
            final Object a = k.attachment();
            i.remove();

            if (a instanceof AbstractNioChannel) {
                processSelectedKey(k, (AbstractNioChannel) a);
            } else {
                @SuppressWarnings("unchecked")
                NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
                processSelectedKey(k, task);
            }

            if (!i.hasNext()) {
                break;
            }

            if (needsToSelectAgain) {
                selectAgain();
                selectedKeys = selector.selectedKeys();
                
                if (selectedKeys.isEmpty()) {
                    break;
                } else {
                    i = selectedKeys.iterator();
                }
            }
        }
    }

这是在openSelector中注入进Selector的SelectedKeys失败的情况下,直接遍历Selector本身的SelectedKeys,和processSelectedKeysOptimized没有差别。

再回到run方法中,接下来需要调用runAllTasks方法处理任务队列中的任务:

protected boolean runAllTasks(long timeoutNanos) {
        fetchFromScheduledTaskQueue();
        Runnable task = pollTask();
        if (task == null) {
            afterRunningAllTasks();
            return false;
        }

        final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
        long runTasks = 0;
        long lastExecutionTime;
        for (;;) {
            safeExecute(task);

            runTasks ++;

            if ((runTasks & 0x3F) == 0) {
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                if (lastExecutionTime >= deadline) {
                    break;
                }
            }

            task = pollTask();
            if (task == null) {
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                break;
            }
        }

        afterRunningAllTasks();
        this.lastExecutionTime = lastExecutionTime;
        return true;
    }

先调用fetchFromScheduledTaskQueue方法:

	private boolean fetchFromScheduledTaskQueue() {
        long nanoTime = AbstractScheduledEventExecutor.nanoTime();
        Runnable scheduledTask  = pollScheduledTask(nanoTime);
        while (scheduledTask != null) {
            if (!taskQueue.offer(scheduledTask)) {
                // No space left in the task queue add it back to the scheduledTaskQueue so we pick it up again.
                scheduledTaskQueue().add((ScheduledFutureTask<?>) scheduledTask);
                return false;
            }
            scheduledTask  = pollScheduledTask(nanoTime);
        }
        return true;
    }

通过pollScheduledTask不断地从延时任务队列获取到期的任务,将到期的任务添加到taskQueue任务队列中,为上面的runAllTasksFrom执行做准备;若是添加失败,再把它放进延时任务队列。

首先获取nanoTime,调用pollScheduledTask方法传入nanoTime:

	protected final Runnable pollScheduledTask(long nanoTime) {
        assert inEventLoop();

        Queue<ScheduledFutureTask<?>> scheduledTaskQueue = this.scheduledTaskQueue;
        ScheduledFutureTask<?> scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek();
        if (scheduledTask == null) {
            return null;
        }

        if (scheduledTask.deadlineNanos() <= nanoTime) {
            scheduledTaskQueue.remove();
            return scheduledTask;
        }
        return null;
    }

从延时任务队列中获取队首的任务scheduledTask,若是scheduledTask的deadlineNanos小于等于nanoTime,说明该任务到期。

回到runAllTasks方法执行任务,调用runAllTasksFrom方法传入任务队列执行任务:

	protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
        Runnable task = pollTaskFrom(taskQueue);
        if (task == null) {
            return false;
        }
        for (;;) {
            safeExecute(task);
            task = pollTaskFrom(taskQueue);
            if (task == null) {
                return true;
            }
        }
    }

调用pollTaskFrom不断地从任务队列队首获取任务,然后执行,直到没有任务:

	protected static Runnable pollTaskFrom(Queue<Runnable> taskQueue) {
        for (;;) {
            Runnable task = taskQueue.poll();
            if (task == WAKEUP_TASK) {
                continue;
            }
            return task;
        }
    }

WAKEUP_TASK :

	private static final Runnable WAKEUP_TASK = new Runnable() {
        @Override
        public void run() {
        }
    };

safeExecute方法:

	protected static void safeExecute(Runnable task) {
        try {
            task.run();
        } catch (Throwable t) {
            logger.warn("A task raised an exception. Task: {}", task, t);
        }
    }

回到runAllTasks方法,当所有到期任务执行完毕后,根据ranAtLeastOne判断是否需要修改最后一次执行时间lastExecutionTime,最后调用afterRunningAllTasks方法,该方法是在SingleThreadEventLoop中实现的:

	protected void afterRunningAllTasks() {
        runAllTasksFrom(tailTasks);
    }

这里执行了tailTasks队列的任务,runAllTasks方法到这里就执行完毕了。

runAllTasks(long timeoutNanos)方法:

	protected boolean runAllTasks(long timeoutNanos) {
        fetchFromScheduledTaskQueue();
        Runnable task = pollTask();
        if (task == null) {
            afterRunningAllTasks();
            return false;
        }

        final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
        long runTasks = 0;
        long lastExecutionTime;
        for (;;) {
            safeExecute(task);

            runTasks ++;

            if ((runTasks & 0x3F) == 0) {
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                if (lastExecutionTime >= deadline) {
                    break;
                }
            }

            task = pollTask();
            if (task == null) {
                lastExecutionTime = ScheduledFutureTask.nanoTime();
                break;
            }
        }

        afterRunningAllTasks();
        this.lastExecutionTime = lastExecutionTime;
        return true;
    }

与runAllTasks方法的逻辑类似,但是如果执行到了第64个任务,则判断是否达到了超时时间deadline,如果是则结束,剩余的留到下一次执行,否则继续执行。

回到run方法,轮询完毕并执行完任务后,调用isShuttingDown方法,在之前的CAS操作中,state已经变为了ST_SHUTTING_DOWN(3),调用closeAll方法:

private void closeAll() {
        selectAgain();
        Set<SelectionKey> keys = selector.keys();
        Collection<AbstractNioChannel> channels = new ArrayList<AbstractNioChannel>(keys.size());
        for (SelectionKey k: keys) {
            Object a = k.attachment();
            if (a instanceof AbstractNioChannel) {
                channels.add((AbstractNioChannel) a);
            } else {
                k.cancel();
                @SuppressWarnings("unchecked")
                NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
                invokeChannelUnregistered(task, k, null);
            }
        }

        for (AbstractNioChannel ch: channels) {
            ch.unsafe().close(ch.unsafe().voidPromise());
        }
    }

先调用selectAgain方法:

	private void selectAgain() {
        needsToSelectAgain = false;
        try {
            selector.selectNow();
        } catch (Throwable t) {
            logger.warn("Failed to update SelectionKeys.", t);
        }
    }

通过这次的轮询,将当前仍有事件就绪的JDK的SelectionKey中绑定的Netty的Channel添加到channels集合中,遍历这个集合,通过unsafe的close方法关闭Netty的Channel。

回到run方法中,紧接着再调用confirmShutdown()进行判断:

protected boolean confirmShutdown() {
        if (!isShuttingDown()) {
            return false;
        }

        if (!inEventLoop()) {
            throw new IllegalStateException("must be invoked from an event loop");
        }

        cancelScheduledTasks();

        if (gracefulShutdownStartTime == 0) {
            gracefulShutdownStartTime = ScheduledFutureTask.nanoTime();
        }

        if (runAllTasks() || runShutdownHooks()) {
            if (isShutdown()) {
                // Executor shut down - no new tasks anymore.
                return true;
            }

            if (gracefulShutdownQuietPeriod == 0) {
                return true;
            }
            wakeup(true);
            return false;
        }

        final long nanoTime = ScheduledFutureTask.nanoTime();

        if (isShutdown() || nanoTime - gracefulShutdownStartTime > gracefulShutdownTimeout) {
            return true;
        }

        if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod) {
            wakeup(true);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // Ignore
            }

            return false;
        }

        return true;
    }

经过两个if判断之后首先调用cancelScheduledTasks方法取消计划任务:

	protected void cancelScheduledTasks() {
        assert inEventLoop();
        PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue = this.scheduledTaskQueue;
        if (isNullOrEmpty(scheduledTaskQueue)) {
            return;
        }

        final ScheduledFutureTask<?>[] scheduledTasks =
                scheduledTaskQueue.toArray(new ScheduledFutureTask<?>[scheduledTaskQueue.size()]);

        for (ScheduledFutureTask<?> task: scheduledTasks) {
            task.cancelWithoutRemove(false);
        }

        scheduledTaskQueue.clearIgnoringIndexes();
    }

遍历队列中的任务并调用cancelWithoutRemove方法取消任务:

	boolean cancelWithoutRemove(boolean mayInterruptIfRunning) {
        return super.cancel(mayInterruptIfRunning);
    }

	public boolean cancel(boolean mayInterruptIfRunning) {
        if (RESULT_UPDATER.compareAndSet(this, null, CANCELLATION_CAUSE_HOLDER)) {
            checkNotifyWaiters();
            notifyListeners();
            return true;
        }
        return false;
    }

到这里run方法就结束了。

回到doStartThread方法,再finally块中,首先是对一些状态的判断,最主要的一步是调用cleanup方法关闭selector:

	protected void cleanup() {
        try {
            selector.close();
        } catch (IOException e) {
            logger.warn("Failed to close a selector.", e);
        }
    }

最后回到MultithreadEventExecutorGroup的构造方法中,再次遍历children组中已经生成的EventExecutor,判断是否已经终止,如果返回值为false,调用awaitTermination(long timeout, TimeUnit unit)方法使其终止。

再来看看没有发生异常的情况,调用chooserFactory.newChooser(children)方法产生EventExecutorChooser对象。

创建FutureListener对象,对每个EventExecutor设置中断监听,最后通readonlyChildren对象保存,至此NioEventLoopGroup的创建结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty 是一个基于 NIO 的客户端、服务器端编程框架,使用 Java 语言编写。它提供了一种高效、可靠、可扩展的异步事件驱动网络编程模型,可以简化网络编程的开发流程。 下面是 Netty码剖析: 1. Bootstrap 类:这是 Netty 启动类,它提供了启动客户端和服务器的方法。其中,ServerBootstrap 类用于启动服务器端应用,Bootstrap 类用于启动客户端应用。 2. Channel 类:这是 Netty 中最核心的类,表示一个通道,可以用来进行数据的读写操作。它继承了 Java NIO 中的 Channel 接口,并添加了一些新的方法和属性,如ChannelPipeline、ChannelHandlerContext 等。 3. ChannelPipeline 类:这是 Netty 中的另一个核心类,表示一组 ChannelHandler 的有序列表,用于管理数据的处理流程。在 Netty 中,一个 Channel 对象可以有多个 ChannelPipeline 对象,每个 ChannelPipeline 对象包含多个 ChannelHandler 对象。 4. ChannelHandlerContext 类:这是 Netty 中的上下文对象,表示一个 ChannelHandler 对象和它所在的 ChannelPipeline 对象之间的关联关系。它提供了一些方法,可以访问 ChannelPipeline 中的其他 ChannelHandler 对象。 5. ChannelFuture 类:这是 Netty 中的异步操作结果对象,表示一个异步操作的状态和结果。当一个异步操作完成时,会通知关联的 ChannelFuture 对象,从而使应用程序能够得到异步操作的结果。 6. EventLoop 类:这是 Netty 中的事件循环对象,用于处理所有的 I/O 事件和任务。在 Netty 中,一个 EventLoop 对象会被多个 Channel 对象共享,它负责调度和执行所有与这些 Channel 相关的事件和任务。 7. ByteBuf 类:这是 Netty 中的字节缓冲区对象,用于存储和操作字节数据。与 Java NIO 中的 ByteBuffer 对象相比,ByteBuf 提供了更加灵活和高效的读写方式。 8. ChannelHandler 接口:这是 Netty 中的处理器接口,用于处理读写事件和状态变化事件。它提供了多个方法,如 channelActive、channelRead、channelWrite 等,用于处理不同类型的事件。 以上是 Netty码剖析,了解这些核心类和接口可以更好地理解和使用 Netty 框架。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值