2022-05-29_netty中SingleThreadEventExecutor线程创建过程分析学习笔记

20220529_netty中SingleThreadEventExecutor线程创建过程分析学习笔记

1概述

SingleThreadEventExecutor线程本质就是原生ThreadPoolExecutor线程的创建。

可借助章节2测试代码进行源码走读,本节主要有一下几点:

  1. ThreadPoolExecutor线程的创建、任务的提交
  2. SingleThreadEventExecutor线程的创建、任务的提交
image-20220529201819422.png

1.1ThreadPoolExecutor线程的创建、任务的提交

1.1.1ThreadPoolExecutor内置threadFactory

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

1.1.2newThread创建线程的方法

static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            // 线程名称:pool-1-thread-1
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        // 创建线程
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

1.1.3真正Jdk线程创建的地方

// C:\Program Files\Java\jdk1.8.0_60\src.zip!\java\util\concurrent\ThreadPoolExecutor.java
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
    if (addWorker(command, true))
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
        }
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            w = new Worker(firstTask);  // 开始创建线程
 /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this); // 调用1.2.2中的方法
        }

1.2SingleThreadEventExecutor线程的创建、任务的提交

// 确保线程值启动一次,并发安全性  
private static final AtomicIntegerFieldUpdater STATE_UPDATER =
            AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state");
image-20220529201112198.png
image-20220529201131131.png

1.2.1SingleThreadEventExecutor抽象类关系图

image-20220330140953543.png
  1. SingleThreadEventExecutor抽象类:延时任务,获取待执行和过期任务,并执行,内置Queue taskQueue。

  2. SingleThreadEventLoop抽象类:实现EventLoopGroup接口中的next,注册等方法,内置额外的时间循环任务队列,tailTasks queue,作为参数给SingleThreadEventExecutor.runAllTasksFrom调用,问题来了,taskQueue不够吗?

    protected final boolean runAllTasksFrom(Queue taskQueue) {。
    
  1. DefaultEventLoop:无限循环,实现从队列中取任务,执行任务等一些列的。
// E:\workdirectory\Dev\study\netty-4.1\transport\src\main\java\io\netty\channel\DefaultEventLoop.java

// 实现了SingleThreadEventExecutor抽象类的run方法。
@Override
    protected void run() {
        for (;;) {
            // 1.调用SingleThreadEventExecutor.takeTask获取任务。
            Runnable task = takeTask();
            if (task != null) {
                task.run();
                // 3.调用SingleThreadEventExecutor.updateLastExecutionTime
                updateLastExecutionTime();
            }

            // 3.调用SingleThreadEventExecutor.confirmShutdown
            if (confirmShutdown()) {
                break;
            }
        }
    }

1.2.2线程的创建逻辑

1.2.2.1构建SingleThreadEventExecutor执行器

@Test
    public void testWrappedExecutorIsShutdown() {
        // 1.设定一个线程
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        final SingleThreadEventExecutor executor =
                        new SingleThreadEventExecutor(null, executorService, false) {

1.2.2.1包装原生Jdkexecutor

protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
    // 线程执行器的包装类:ThreadExecutorMap
    // 参数1 executor:ThreadPerTaskExecutor
    // 参数2 this:SingleThreadEventExecutor
    this.executorWrap = ThreadExecutorMap.apply(executor, this);
    this.executor = ThreadExecutorMap.apply(executor, this);
// E:\workdirectory\Dev\study\netty-4.1\common\src\main\java\io\netty\util\internal\ThreadExecutorMap.java
return new Executor() {
    @Override
    public void execute(final Runnable command) {
        // step1:对原始 executor进行包装
        // 后面外界的入口execute-->apply、execute
        // 注意 threadPoolExecutor:java.util.concurrent.ThreadPoolExecutor
        // 提交任务的时候,会在这里创建线程,并执行这个runnable方法,runnable内部是一个取任务的无线循环
        // 但一直在这个工作线程中执行 while (!confirmShutdown()) {
        executor.execute(apply(command, eventExecutor));
    }
};
// E:\workdirectory\Dev\study\netty-4.1\common\src\main\java\io\netty\util\internal\ThreadExecutorMap.java
// apply逻辑分析,设置当前的事件执行器,返回业务runnable,并真正的线程池提交执行
public static Runnable apply(final Runnable command, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(command, "command");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Runnable() {
            @Override
            public void run() {
                setCurrentEventExecutor(eventExecutor);
                try {
                    // step2:调用 doStartThread中的execute runnable,循环取任务执行
                    // command 实际为:@@@@@@那方法
                    command.run();
                } finally {
                    setCurrentEventExecutor(null);
                }
            }
        };
    }

1.2.2.2任务提交(首次进行线程创建)

// E:\workdirectory\Dev\study\netty-4.1\common\src\main\java\io\netty\util\concurrent\SingleThreadEventExecutor.java
private void execute(Runnable task, boolean immediate) { // immediate:true
        boolean inEventLoop = inEventLoop();
        addTask(task); // 业务的runnable方法
 private void execute(Runnable task, boolean immediate) {
        boolean inEventLoop = inEventLoop();
        addTask(task);
        if (!inEventLoop) {
            startThread();
    private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {  // 人工构建一个runnable任务,循环调用takeTask方法
// E:\workdirectory\Dev\study\netty-4.1\common\src\main\java\io\netty\util\concurrent\SingleThreadEventExecutor.java
private void doStartThread() {
        assert thread == null;
        // 执行 2.1.3中的方法
        executor.execute(
***********************************************************************  
            new Runnable() { 
           
            @Override
            public void run() { // 这个方法实际一直不会结束的@@@@@@
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    // 去队列里取任务执行
                    // 执行模板方法,实现类里的 SingleThreadEventLoopTest.java,for (;;) {
                    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) {
                        if (logger.isErrorEnabled()) {
                            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. At this point the event loop
                        // is in ST_SHUTTING_DOWN state still accepting tasks which is needed for
                        // graceful shutdown with quietPeriod.
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }

                        // Now we want to make sure no more tasks can be added from this point. This is
                        // achieved by switching the state. Any new tasks beyond this point will be rejected.
                        for (;;) {
                            int oldState = state;
                            if (oldState >= ST_SHUTDOWN || STATE_UPDATER.compareAndSet(
                                    SingleThreadEventExecutor.this, oldState, ST_SHUTDOWN)) {
                                break;
                            }
                        }

                        // We have the final set of tasks in the queue now, no more can be added, run all remaining.
                        // No need to loop here, this is the final pass.
                        confirmShutdown();
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            // Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
                            // the future. The user may block on the future and once it unblocks the JVM may terminate
                            // and start unloading classes.
                            // See https://github.com/netty/netty/issues/6596.
                            FastThreadLocal.removeAll();

                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.countDown();
                            int numUserTasks = drainTasks();
                            if (numUserTasks > 0 && logger.isWarnEnabled()) {
                                logger.warn("An event executor terminated with " +
                                        "non-empty task queue (" + numUserTasks + ')');
                            }
                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        }
***********************************************************************
        );
    }

2测试代码

@Test
public void testWrappedExecutorIsShutdown() throws InterruptedException {
    // 1.构建ExecutorService
    ExecutorService executorService = Executors.newSingleThreadExecutor();

    // 2.构建SingleThreadEventExecutor
    final SingleThreadEventExecutor executor =
        new SingleThreadEventExecutor(null, executorService, false) {
        @Override
        protected void run() {
            while (!confirmShutdown()) {
                Runnable task = takeTask();
                if (task != null) {
                    task.run();
                }
            }
        }
    };
    // 3.任务提交
    executor.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println("do it");
            // Noop.
        }
    });
    TimeUnit.SECONDS.sleep(100);
    executorService.shutdownNow();
    assertTrue(executor.isShutdown());

参考

你可能感兴趣的:(2022-05-29_netty中SingleThreadEventExecutor线程创建过程分析学习笔记)