Netty事件循环组原理五

Executor

Executor是一个接口,这个接口负责执行提交给它的任务(Runnable对象)。这个接口能够使“任务提交”与“任务执行”解耦。即某人只要把任务提交给Executor就好了,至于它怎么给任务分配线程去执行,你就不用管了。但是,Executor接口并不严格要求执行操作是异步的。

public interface Executor {
    //在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,
    //这由 Executor 实现决定。
    void execute(Runnable command);
}
ExecutorService

ExecutorService是Java中对线程池定义的一个接口,它在java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法:

ScheduledExecutorService

ScheduledExecutorService是基于ExecutorService的功能实现的延迟和周期执行任务的功能。

每个任务以及每个任务的每个周期都会提交到线程池中由线程去执行,所以任务在不同周期内执行它的线程可能是不同的。ScheduledExecutorService接口的默认实现类是ScheduledThreadPoolExecutor。在周期执行的任务中,如果任务执行时间大于周期时间,则会以任务时间优先,等任务执行完毕后才会进入下一次周期。

schedule方法的实现原理

scheduleAtFixedRate()和scheduleWithFixedDelay()实现原理

1、为什么用优先队列(小顶堆)而不是有序的数组或者链表?

因为优先队列只需要确保局部有序,它的插入、删除操作的复杂度都是O(log n);而有序数组的插入和删除复杂度为O(n);链表的插入复杂度为O(n),删除复杂度为O(1)。总体而言优先队列性能最好。

2、为什么自己重复实现了DelayedWorkQueue,而不对PriorityQueue进行封装或者直接用DelayQueue、PriorityBlockingQueue?

暂时没想到原因。按理说DelayedWorkQueue能做到的,DelayQueue基本都可以做到,实现不明白为何要重复造轮子。

由于之前提到过,事件循环组需要做一些周期性调度的工作,所以让它继承ScheduledExecutorService。

EventExecutorGroup

EventExecutorGroup 继承自 JDK 的 ScheduledExecutorService,即可以执行定时任务,也可以像普通的任务执行器一样提交任务去执行。它是用来管理 group 中的 EventExecutor 的。它负责提供EventExecutor以通过其next()方法使用。 除此之外,它还负责处理它们的生命周期并允许以全局方式关闭它们。

EventExecutorGroup自身不执行任务,而是将任务submit或者schedule给自己管理的EventExecutor的分组,至于提交给哪一个EventExecutor,一般是通过next()方法选择一个EventExecutor,因为 Group 中有很多个 EventExecutor,至于具体返回哪一个 EventExecutor,还是由具体的实现类来实现的。

EventExecutor

它是一个特殊的EventExecutorGroup,组里只有一个线程,next永远指向自己。

public interface EventExecutor extends EventExecutorGroup {
    //Returns a reference to itself.
    //这里的 next 方法,返回的是 EventExecutor 本身。
    @Override
    EventExecutor next();
    //Return the EventExecutorGroup which is the parent of this EventExecutor
    //因为 EventExecutor 是由 EventExecutorGroup 来管理的,所以 EventExecutor 中还存在一个
    //parent 方法,用来返回管理 EventExecutor 的 EventExecutorGroup
    EventExecutorGroup parent();
    //EventExecutor 中新加了两个inEventLoop 方法,用来判断给定的线程是否在event loop 中执行。
    boolean inEventLoop();
    boolean inEventLoop(Thread thread);
}
EventLoopGroup

继承了EventExecutorGroup,提供注册Channel能力的EventExecutorGroup。EventExecutorGroup的next是返回的经过负载均衡器筛选出的任何一个EventExecutor,而EventLoopGroup的next是返回的下一个,把这些EventLoop串起来了。是一个循环的过程。

public interface EventLoopGroup extends EventExecutorGroup {
    //Return the next {@link EventLoop} to use
    @Override
    EventLoop next();
    ChannelFuture register(Channel channel);
}

从一开始,有一个执行器叫EventExecutorGroup,它继承自ScheduledExecutorService,那么就拥有了一些调度执行的基本功能,且可以通过next方法获取组里其中一个EventExecutor,EventExecutor是EventExecutorGroup里面一个执行事件的执行体,那么这个执行体又是一个特殊的EventExecutorGroup,因为一个人也是一个组,只不过组里面只有一个线程,那么为什么引入了EventLoopGroup呢?有时候我们想注册Channel,而且我们想把这些线程连起来,这时候通过next循环这个线程数组。

AbstractEventExecutorGroup

AbstractEventExecutorGroup只是对接口进行了抽象实现,将部分方法的实现的委托给next()方法返回的EventExecutor,但是没具体实现next()方法。

MultithreadEventExecutorGroup
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
    private final EventExecutor[] children;
    private final EventExecutorChooserFactory.EventExecutorChooser chooser;
    //如果threadFactory不为空,那么会调用ThreadPerTaskExecutor
    protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
        this(nThreads, threadFactory == null ? null : new ThreadPerTaskExecutor(threadFactory), args);
    }
    //初始化选择器
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }
        //防止直接new的这个构造函数,executor传的空
        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        //实例化EventExecutor数组
        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 {
                ...
            }
        }
        //创建选择器
        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);
        //unmodifiableSet的底层就是增删改的方法都返回异常
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }
    //由子类创建执行器
    protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;
    @Override
    public EventExecutor next() {
        return chooser.next();
    }
}
public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;
    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        this.threadFactory = ObjectUtil.checkNotNull(threadFactory, "threadFactory");
    }
    @Override
    public void execute(Runnable command) {
        threadFactory.newThread(command).start();
    }
}
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
    public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
    private DefaultEventExecutorChooserFactory() { }
    @Override
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        //判断是不是2的倍数
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }
    private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;
    }
    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 {
        private final AtomicLong idx = new AtomicLong();
        private final EventExecutor[] executors;
        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }
        @Override
        public EventExecutor next() {
            //防止符号溢出,所以使用 Math.abs
            return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }
}
MultithreadEventLoopGroup
public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup {
    private static final int DEFAULT_EVENT_LOOP_THREADS;//默认线程数
    static {
        //CPU的核心数*2
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
            "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
    }
    protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
    @Override
    public EventLoop next() {
        return (EventLoop) super.next();
    }
    //它也没有实现
    @Override
    protected abstract EventLoop newChild(Executor executor, Object... args) throws Exception;

    @Override
    public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }
}

CPU执行任务,每个核都是从一个RunQueue中获取,此时是单核单线程,执行IO期间这个线程一直处于等待状态,CPU就处于空转状态,浪费资源。

如果是单核2个线程,那么第一个线程处于IO等待时,可以继续执行第二个。

如果是单核3个线程,那么第一个线程IO等待结束时,就会重新放入RunQueue中等待CPU调度,但是由于前面还有2个线程都在执行,所以可能很久才能轮到第一个线程继续执行。

单核4个线程...

所以设置核心数*2比较合理。

NioEventLoopGroup
public class NioEventLoopGroup extends MultithreadEventLoopGroup {
    //使用CPU核心*2
    public NioEventLoopGroup() {
        this(0);
    }
    @Override
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
                                ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);
    }
}
NioEventLoop
public final class NioEventLoop extends SingleThreadEventLoop {
    NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,
                 EventLoopTaskQueueFactory queueFactory) {
        super(parent, executor, false, newTaskQueue(queueFactory), newTaskQueue(queueFactory),
              rejectedExecutionHandler);
        //给selectorProvider赋值
        this.provider = ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");
        //选择策略
        this.selectStrategy = ObjectUtil.checkNotNull(strategy, "selectStrategy");
        //打开Selector
        final SelectorTuple selectorTuple = openSelector();
        this.selector = selectorTuple.selector;
        this.unwrappedSelector = selectorTuple.unwrappedSelector;
    }
}

SingleThreadEventLoop

基于单线程的EventLoop抽象类,单线程执行所有的任务,主要增加了Channel注册到EventLoop上

public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
    private final Queue<Runnable> tailTasks;
    protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, Queue<Runnable> taskQueue, Queue<Runnable> tailTaskQueue,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, taskQueue, rejectedExecutionHandler);
        //EventLoop事件循环的一轮runAllTasks结束后,执行收尾任务
        //比如一些需要在一轮事件循环后执行的任务,就像标题说的,
        //用户想统计执行一次事件循环花了多长时间就可以调用此方法将自己实现的
        //统计业务封装为task在提交给NioEventLoop线程,当NIO线程执行完一次事件循环,
        //就会自动执行这个task
        tailTasks = ObjectUtil.checkNotNull(tailTaskQueue, "tailTaskQueue");
    }
    @Override
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }
}
SingleThreadEventExecutor

SingleThreadEventExecutor使用的是单线程来执行提交的tasks,所以此时有两个队列,一个是父类的scheduledTaskQueue,一个是自己的taskQueue

public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
    private final Queue<Runnable> taskQueue;
    private volatile Thread thread;
    protected SingleThreadEventExecutor(
        EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) {
        this(parent, new ThreadPerTaskExecutor(threadFactory), addTaskWakesUp);
    }
    protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, Queue<Runnable> taskQueue,
                                        RejectedExecutionHandler rejectedHandler) {
        super(parent);
        this.addTaskWakesUp = addTaskWakesUp;
        this.maxPendingTasks = DEFAULT_MAX_PENDING_EXECUTOR_TASKS;
        this.executor = ThreadExecutorMap.apply(executor, this);
        this.taskQueue = ObjectUtil.checkNotNull(taskQueue, "taskQueue");
        this.rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }
    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 {
                   ...
                }
            }
        });
    }
}
AbstractScheduledEventExecutor

AbstractScheduledEventExecutor继承自AbstractEventExecutor,它内部使用了一个PriorityQueue来存储包含定时任务的ScheduledFutureTask,从而实现定时任务的功能:

public abstract class AbstractScheduledEventExecutor extends AbstractEventExecutor {
    PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值