netty- runAllTasks

本文详细解析了任务调度与执行的内部机制,包括从任务队列中获取并执行任务的过程,超时检查策略,以及执行后的回调处理。关键步骤涉及从计划任务队列中轮询任务,判断任务是否已到期,将到期任务移至任务队列,以及在执行一定数量任务后检查是否超过预设时间限制。

runAllTasks()
1.从schedule任务获取,加入到taskQueue
2.从taskQueue获取任务
3. 获取到的任务执行run()
4. 每获取64个任务计算一次是否超时
5. 执行 afterRunningAllTasks()

 /**
     * Poll all tasks from the task queue and run them via {@link Runnable#run()} method.  This method stops running
     * the tasks in the task queue and returns if it ran longer than {@code 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 ++;

            // Check timeout every 64 tasks because nanoTime() is relatively expensive.
            // XXX: Hard-coded value - will make it configurable if it is really a problem.
            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()
1.循环从scheduledTaskQUeue取任务,然后加入到taskQueue
2.若加入不了,再塞回到scheduledTaskQUeue,返回false

rivate 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()
1.先从scheduledTaskQueue.peer(),然后计算是否超时,没有就remove(),返回task

 /**
     * Return the {@link Runnable} which is ready to be executed with the given {@code nanoTime}.
     * You should use {@link #nanoTime()} to retrieve the the correct {@code 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;
    }

pollTask()
从taskQueue.poll取任务

    protected Runnable pollTask() {
        assert inEventLoop();
        return pollTaskFrom(taskQueue);
    }

pollTaskFrom()
1.从taskQueue.poll取任务
2.若为WAKEUP_TASK,继续取下一个


    protected static Runnable pollTaskFrom(Queue<Runnable> taskQueue) {
        for (;;) {
            Runnable task = taskQueue.poll();
            if (task == WAKEUP_TASK) {
                continue;
            }
            return task;
        }
    }
 /**
     * Try to execute the given {@link Runnable} and just log if it throws a {@link Throwable}.
     */
    protected static void safeExecute(Runnable task) {
        try {
            task.run();
        } catch (Throwable t) {
            logger.warn("A task raised an exception. Task: {}", task, t);
        }
    }

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

runAllTasksFrom()
1.从指定的queue.poll()取任务,为null返回false
2.有任务就直接执行,循环获取

/**
     * Runs all tasks from the passed {@code taskQueue}.
     *
     * @param taskQueue To poll and execute all tasks.
     *
     * @return {@code true} if at least one task was executed.
     */
    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;
            }
        }
    }
Caused by: io.lettuce.core.RedisException: Connection closed at io.lettuce.core.protocol.DefaultEndpoint.notifyDrainQueuedCommands(DefaultEndpoint.java:679) ~[lettuce-core-6.1.10.RELEASE.jar!/:6.1.10.RELEASE] at io.lettuce.core.protocol.CommandHandler.channelInactive(CommandHandler.java:358) ~[lettuce-core-6.1.10.RELEASE.jar!/:6.1.10.RELEASE] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:303) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.lettuce.core.protocol.RedisHandshakeHandler.channelInactive(RedisHandshakeHandler.java:89) ~[lettuce-core-6.1.10.RELEASE.jar!/:6.1.10.RELEASE] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:305) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.lettuce.core.ChannelGroupListener.channelInactive(ChannelGroupListener.java:69) ~[lettuce-core-6.1.10.RELEASE.jar!/:6.1.10.RELEASE] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:305) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:301) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe$7.run(AbstractChannel.java:813) ~[netty-transport-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:413) ~[netty-transport-classes-epoll-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.101.Final.jar!/:4.1.101.Final] ... 1 common frames omitted 什么错误
最新发布
10-10
2025-09-06 09:00:49,468 WARN [acceptorWorkerGroup-3-1][io.netty.channel.ChannelInitializer] Failed to initialize a channel. Closing: [id: 0x6a2a1e54, L:/10.7.54.36:30930 - R:/10.6.9.43:52758] java.lang.VerifyError: Local variable table overflow Exception Details: Location: io/netty/handler/codec/ByteToMessageDecoder.<init>()V @18: fload_3 Reason: Local index 3 is invalid Bytecode: 0x0000000: 2ab7 017f 2ab2 0124 b500 382a 03b5 0059 0x0000010: 2a00 25b5 0022 2ab6 0182 2a4c a700 0c00 0x0000020: 00bf 4d00 105e 0010 0160 b901 6603 00a7 0x0000030: fff6 a7ff f6b1 Exception Handler Table: bci [28, 31] => handler: 34 Stackmap Table: full_frame(@31,{},{Object[#211]}) full_frame(@34,{Object[#2],Object[#2]},{Object[#211]}) append_frame(@50,Object[#211]) chop_frame(@53,1) at com.huatai.xtrade.xstep.commu.acceptor.XStepAcceptor$XStepNormalChannelInitializer.initChannel(XStepAcceptor.java:421) ~[xstep-1.3.22-SNAPSHOT.jar!/:?] at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:129) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:112) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.callHandlerAdded(AbstractChannelHandlerContext.java:989) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:610) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline.access$100(DefaultChannelPipeline.java:46) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1461) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1126) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:651) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:514) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:427) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:495) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-all-4.1.33.Final.jar!/:4.1.33.Final] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_202]
09-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值