<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>yuhaowin</title>
    <link>https://blog.yuhaowin.com</link>
    <description>yuhaowin&#39;s blog</description>
    <language>zh-cn</language>
    <item>
      <title>OpenClaw 源代码全链路解析：一条消息背后的十层旅程</title>
      <link>https://blog.yuhaowin.com/2026/2026-03-15-openclaw-source-analysis/</link>
      <description>&lt;h1&gt;OpenClaw 源代码全链路解析：一条消息背后的十层旅程&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;当你向 OpenClaw 发出一句&amp;quot;你好&amp;quot;，从按下发送键到看见回复，背后到底经历了什么？本文基于 OpenClaw 源码，逐层拆解其完整执行链路。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;引言&lt;/h2&gt;&#xA;&lt;p&gt;OpenClaw 是近期 AI 领域最受关注的开源项目之一。很多人以为它的核心是那个聊天框，但本质上，&lt;strong&gt;它首先是一个本地优先（Local-First）的网关平台&lt;/strong&gt;。只有先把网关跑起来，建立统一的会话管理、渠道管理、工具管理和事件分发能力，来自不同渠道的消息才能汇总进来，进入后续的处理流程。&lt;/p&gt;&#xA;&lt;p&gt;下面，我们就来一层层拆开这套系统，看看一条用户消息是如何被处理的。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/03/15/170955.png&#34; alt=&#34;OpenClaw 消息处理全链路 - 10 层旅程总览&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第一层：网关启动 - 以 WhatsApp 渠道为例&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/843e3c1efbbd4844a494b873a68aedea252488f3/extensions/whatsapp/src/auto-reply/monitor.ts&#34;&gt;&lt;code&gt;extensions/whatsapp/src/auto-reply/monitor.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;monitorWebChannel&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;整个流程的起点和大模型没有任何关系，而是从&lt;strong&gt;网关的启动&lt;/strong&gt;开始。&lt;/p&gt;&#xA;&lt;p&gt;启动过程分为以下几步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;检查网络连接&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;加载 &lt;code&gt;openclaw.json&lt;/code&gt; 总配置文件&lt;/strong&gt;，其中包含智能体、渠道、环境变量、鉴权信息、模型配置等所有核心字段&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;解析当前账号&lt;/strong&gt;（如 WhatsApp 账号）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/843e3c1efbbd4844a494b873a68aedea252488f3/extensions/whatsapp/src/auto-reply/monitor.ts#L145-L148&#34;&gt;进入持续循环&lt;/a&gt;&lt;/strong&gt;：创建消息处理器(createWebOnMessageHandler)、启动渠道监听器(listener)、设置心跳机制(heartbeat)和看门狗定时器(watchdogTimer)、处理连接断开与重连、持续更新系统运行状态&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;只有这整套流程全部完成，网关成功启动，OpenClaw 才算正式进入就绪状态，随时准备接收用户消息。没有网关的支撑，后面所有的能力都无从谈起。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第二层：消息接入与标准化&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts&#34;&gt;&lt;code&gt;extensions/whatsapp/src/inbound/monitor.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;用户消息进入 OpenClaw 的第一站，并不是直接被转发给大模型，而是先进入&lt;strong&gt;消息监听与接入层&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;系统通过 &lt;code&gt;sock.ev.on(&amp;quot;messages.upsert&amp;quot;)&lt;/code&gt; 这个事件监听器持续监听新消息，一旦有消息到达，立刻启动以下流程：&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts#L179&#34;&gt;2.1 消息去重与高频合并&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;真实的即时通讯环境中，平台经常重复推送消息，用户也可能短时间内连续发送多条。如果直接处理原始消息，很容易导致机器人重复回复。这一步的去重和合并，就是为了过滤噪声，保证后续流程拿到干净、完整的用户需求。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts#L208&#34;&gt;2.2 权限与合法性检查&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;判断消息是否来自允许的用户或群组，是否满足预设的触发规则。不符合规则的消息会被直接过滤，根本不会进入智能体处理流程。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts#L266&#34;&gt;2.3 媒体文件预下载&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;如果用户消息中包含图片、文件等媒体附件，系统会自动下载并保存到本地工作目录，供后续智能体推理时直接访问，完成图片分析、文档读取等操作。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts#L352&#34;&gt;2.4 封装为标准化对象&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;这是整个接入层最关键的一步：把来自不同即时通讯平台、格式千差万别的原始消息，&lt;strong&gt;统一封装成 &lt;code&gt;WebInboundMessage&lt;/code&gt; 对象&lt;/strong&gt;，即系统内部的标准化消息结构。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/inbound/monitor.ts#L385-L394&#34;&gt;2.5 放入防抖队列&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;标准化后的消息被放入防抖队列，防止用户短时间内连续发送大量消息导致系统重复处理，之后触发回调函数，将整理好的消息交给网关进入下一环节。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;本层本质&lt;/strong&gt;：把来自外部世界混乱的、非标准化的用户消息，转化成系统内部可识别、可调度、可处理的标准化事件。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/03/15/171000.png&#34; alt=&#34;消息接入与标准化子流程&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第三层：消息路由与智能体分发&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/auto-reply/monitor/on-message.ts&#34;&gt;&lt;code&gt;extensions/whatsapp/src/auto-reply/monitor/on-message.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;拿到标准化的 &lt;code&gt;WebInboundMessage&lt;/code&gt; 对象后，进入&lt;strong&gt;路由模块&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;并不是所有用户消息都会被送到同一个 AI 模型，由模型自己决定怎么处理。OpenClaw 的设计是：&lt;strong&gt;不同类型的任务，会被分配给不同的智能体来处理&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/auto-reply/monitor/on-message.ts#L67&#34;&gt;3.1 动态加载配置&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;系统通过 &lt;code&gt;createWebOnMessageHandler&lt;/code&gt; 函数创建消息处理入口，同时重新读取最新的系统配置。这是一个关键的工程细节：OpenClaw 的配置支持动态调整，智能体绑定关系、权限规则等都可以在运行时修改，每次处理消息时重新读取配置，确保用的是最新规则。&lt;/p&gt;&#xA;&lt;h3&gt;3.2 解析消息方向&lt;/h3&gt;&#xA;&lt;p&gt;判断消息来自一对一私聊还是群组聊天，同时确定发送者的唯一 ID。群聊场景下，机器人需要判断是否被 @ 或满足触发规则；私聊场景下，通常默认直接处理。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/auto-reply/monitor/on-message.ts#L67&#34;&gt;3.3 智能体路由决策&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;读取 &lt;code&gt;openclaw.json&lt;/code&gt; 配置文件里的 &lt;code&gt;bindings&lt;/code&gt;（绑定规则），通过 &lt;code&gt;resolveAgentRoute&lt;/code&gt; 函数，判断应该由哪个智能体处理当前消息。这样，不同渠道、不同用户、不同类型的消息，都可以被精准分流到对应的智能体。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/auto-reply/monitor/on-message.ts#L76&#34;&gt;3.4 生成会话历史键值&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;buildGroupHistoryKey&lt;/code&gt; 函数，为当前会话生成唯一的历史记录键值——这是实现上下文关联的核心。AI 之所以能&amp;quot;记得&amp;quot;之前的对话，就是因为系统在每次推理前，都会通过这个键值加载对应的历史对话记录。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/c4265a5f166f99b19b6bccaf445463640411c4f2/extensions/whatsapp/src/auto-reply/monitor/on-message.ts#L86-L96&#34;&gt;3.5 安全检查&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Same-phone 模式&lt;/strong&gt;：判断消息是否来自同一台设备，避免机器人对自己发出的消息形成循环回复&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;echoTracker 回声追踪&lt;/strong&gt;：过滤掉刚刚自己发送的消息，避免重复处理同步事件&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;3.6 广播判断&lt;/h3&gt;&#xA;&lt;p&gt;如果满足广播条件，系统让所有需要参与的智能体分别执行一次 &lt;code&gt;processForRoute&lt;/code&gt; 路由处理函数；否则只调用一次对应的路由处理逻辑。&lt;/p&gt;&#xA;&lt;p&gt;最终，消息进入核心处理函数 &lt;code&gt;processMessage&lt;/code&gt;，传递给下一环节。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/03/15/171003.png&#34; alt=&#34;消息路由决策树&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第四层：推理环境准备&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts&#34;&gt;&lt;code&gt;src/auto-reply/reply/get-reply.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;到了这一步，很多人以为系统已经开始调用大模型了——但事实上，它只是完成了所有&lt;strong&gt;幕后准备工作&lt;/strong&gt;，为接下来的推理搭建好完整、干净、信息完备的运行环境。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts#L67-L70&#34;&gt;4.1 最终确认智能体与模型&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;resolveSessionAgentId&lt;/code&gt; 函数最终确定当前会话对应的智能体，以及本次推理要使用的 AI 模型。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts#L106-L109&#34;&gt;4.2 准备工作目录&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;执行 &lt;code&gt;ensureAgentWorkspace&lt;/code&gt; 函数，为当前智能体准备独立的工作目录。智能体运行时经常需要读写文件、下载附件、生成临时结果、执行工具命令，所以每个智能体都有自己的专属工作区。&lt;/p&gt;&#xA;&lt;h3&gt;4.3 媒体与链接深度解析&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;applyMediaUnderstanding&lt;/code&gt;：对图片内容进行深度解析，转化成文本信息&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;applyLinkUnderstanding&lt;/code&gt;：对链接里的网页内容进行解析，转化成文本信息&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;让智能体在正式推理之前，就对用户发送的所有内容有全面完整的理解。&lt;/p&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts#L152-L155&#34;&gt;4.4 初始化会话状态&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;initSessionState&lt;/code&gt; 函数，把对应的历史对话记录完整加载进来。这就是 AI&amp;quot;记忆&amp;quot;的本质——不是真的有记忆，而是每次推理前把历史对话重新加载到上下文里。&lt;/p&gt;&#xA;&lt;h3&gt;4.5 解析特殊控制指令&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;resolveReplyDirectives&lt;/code&gt; 函数，解析消息里的特殊控制指令：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;reset&lt;/code&gt;：重置会话&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;model&lt;/code&gt;：指定使用的模型&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;verbose&lt;/code&gt;：开启详细输出模式&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/think high&lt;/code&gt;：使用更高的推理强度&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/new&lt;/code&gt;：开启全新会话，不加载历史上下文&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts#L305&#34;&gt;4.6 处理内联操作&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;handleInlineActions&lt;/code&gt; 函数处理不需要 AI 推理就能直接完成的操作，比如简单的系统状态查询、内置管理命令。&lt;/p&gt;&#xA;&lt;p&gt;所有准备工作完成后，进入 &lt;a href=&#34;https://github.com/openclaw/openclaw/blob/b2e9221a8c8189b3c9acc020ff8e9b811dbd587e/src/auto-reply/reply/get-reply.ts#L361&#34;&gt;&lt;code&gt;runPreparedReply&lt;/code&gt;&lt;/a&gt; 函数，把会话上下文、模型选择、工具环境、用户消息、运行配置等全部打包传递给后面的流程。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第五层：执行参数转换&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/53462b990d95a34236cd42726e5b73ae6722d849/src/auto-reply/reply/get-reply-run.ts&#34;&gt;&lt;code&gt;src/auto-reply/reply/get-reply-run.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;runPreparedReply&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这一层的作用，是把用户消息和所有配置参数，&lt;strong&gt;转换成完整的、大模型可以直接执行的运行配置&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;最终判断当前消息是否需要进入 AI 推理流程（某些系统指令或已处理消息会在这里直接结束）&lt;/li&gt;&#xA;&lt;li&gt;将会话信息整理成大模型可理解的提示词结构&lt;/li&gt;&#xA;&lt;li&gt;根据用户指令调整模型运行配置（推理强度、会话模式等）&lt;/li&gt;&#xA;&lt;li&gt;校验推理的思考等级和运行策略（简单问答 vs. 复杂多步骤任务规划）&lt;/li&gt;&#xA;&lt;li&gt;处理会话里的消息队列，确保消息按正确顺序进入推理流程&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;完成后，将整理好的参数包传递给 &lt;code&gt;agent-runner.ts&lt;/code&gt;，排队执行下一步流程。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第六层：智能体生命周期调度&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/a472f988d89b2f9cd3fcacfdce8db794b2eac145/src/auto-reply/reply/agent-runner.ts&#34;&gt;&lt;code&gt;src/auto-reply/reply/agent-runner.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这个文件负责管理智能体运行的完整生命周期，是 OpenClaw 保证系统稳定运行的&lt;strong&gt;核心调度中枢&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;调用 &lt;code&gt;runReplyAgent&lt;/code&gt; 把消息放进对应的处理队列，标记为&amp;quot;正在处理&amp;quot;，避免重复处理&lt;/li&gt;&#xA;&lt;li&gt;执行 &lt;code&gt;runMemoryFlushIfNeeded&lt;/code&gt;：在必要时自动保存当前会话的记忆状态&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;长会话记忆的核心机制&lt;/strong&gt;：在长时间对话中，系统需要不断叠加历史会话信息。如果不控制上下文长度，很快会撑爆大模型的上下文窗口导致推理失败。OpenClaw 会在会话信息达到上下文窗口上限时，自动对历史内容进行压缩，然后持久化到记忆文件里——这就是长会话记忆机制的核心实现。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;准备完成后，才进入真正的 AI 调用流程：&lt;code&gt;runAgentTurnWithFallback&lt;/code&gt; 函数。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第七层：执行容错与失败降级&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/a472f988d89b2f9cd3fcacfdce8db794b2eac145/src/auto-reply/reply/agent-runner-execution.ts&#34;&gt;&lt;code&gt;src/auto-reply/reply/agent-runner-execution.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;runAgentTurnWithFallback&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这一层不仅负责调用模型，还&lt;strong&gt;内置了完整的失败重试和降级机制&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;用 &lt;code&gt;crypto.randomUUID&lt;/code&gt; 给本次 AI 调用生成全局唯一标识&lt;/li&gt;&#xA;&lt;li&gt;用 &lt;code&gt;registerAgentRunContext&lt;/code&gt; 注册本次调用的完整上下文，方便后续精准追溯&lt;/li&gt;&#xA;&lt;li&gt;进入&lt;strong&gt;循环执行框架&lt;/strong&gt;：模型调用失败时（网络问题、服务异常、接口限流），按预设策略重试或切换备用模型后端&lt;/li&gt;&#xA;&lt;li&gt;执行 &lt;code&gt;normalizeStreamingText&lt;/code&gt;：清理无意义的心跳标识、静默回复、空文本等噪声&lt;/li&gt;&#xA;&lt;li&gt;进入 &lt;code&gt;runWithModelFallback&lt;/code&gt;，判断执行路径：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;CLI 模式&lt;/strong&gt;：进入 &lt;code&gt;runCliAgent&lt;/code&gt;，交给外部 CLI 后端执行（如 Claude Code、Codex CLI、Gemini CLI）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;嵌入式模式（默认）&lt;/strong&gt;：进入 &lt;code&gt;runEmbeddedPiAgent&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这一层还会持续检查返回结果里的异常信号：会话损坏、上下文溢出、消息顺序错误等，确保不会在基础条件不符合的情况下强行执行模型调用。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第八层：嵌入式智能体准备&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/a472f988d89b2f9cd3fcacfdce8db794b2eac145/src/agents/pi-embedded-runner/run.ts&#34;&gt;&lt;code&gt;src/agents/pi-embedded-runner/run.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;runEmbeddedPiAgent&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;到了这一步，前面所有的准备工作全部完成：执行路径确认、模型选定、容错机制部署、上下文和参数打包完毕。&lt;/p&gt;&#xA;&lt;h3&gt;8.1 确认排队规则&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;resolveSessionLane&lt;/code&gt;：确认本次 AI 调用应该遵守哪条排队规则——会话级顺序执行，还是全局级统一调度。&lt;/p&gt;&#xA;&lt;h3&gt;8.2 确定输出格式&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;resolvedToolResultFormat&lt;/code&gt;：根据消息来自的渠道（WhatsApp、Telegram 等），确定最终输出内容的格式。不同平台的消息能力完全不一样，所以在调用模型之前就确定好适配格式。&lt;/p&gt;&#xA;&lt;h3&gt;8.3 补全模型细节&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;resolveModel&lt;/code&gt;：把当前要使用的模型的所有细节全部补齐，包括完整名称、上下文窗口大小、API 地址、调用方式、默认运行参数等。&lt;/p&gt;&#xA;&lt;h3&gt;8.4 多密钥轮询认证&lt;/h3&gt;&#xA;&lt;p&gt;系统不只使用一个固定的 API 密钥，而是遍历一组认证配置候选项，优先尝试第一个可用的 API 密钥。如果当前密钥认证失败，自动切换到下一个，直到找到可用密钥或遍历完所有候选项。这种&lt;strong&gt;多密钥轮询机制&lt;/strong&gt;在生产环境里可以最大限度避免单密钥限流或失效导致的服务不可用。&lt;/p&gt;&#xA;&lt;h3&gt;8.5 发起单次 AI 调用尝试&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;runEmbeddedAttempt&lt;/code&gt; 函数进行单次 AI 调用尝试，把提示词、会话历史、工具环境、模型参数、认证信息、工作目录全部交给底层的智能体运行时，&lt;strong&gt;正式向大模型发起请求&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第九层：Agent Loop 执行循环&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/89e3969d640cede4636214ecaa658a082bf4513d/src/agents/pi-embedded-runner/run/attempt.ts&#34;&gt;&lt;code&gt;src/agents/pi-embedded-runner/run/attempt.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;runEmbeddedAttempt&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这是整个流程里&lt;strong&gt;真正向大模型发起请求、完成核心推理&lt;/strong&gt;的一步。&lt;/p&gt;&#xA;&lt;h3&gt;9.1 准备运行环境&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;resolveUserPath&lt;/code&gt; 和 &lt;code&gt;resolveSandboxContext&lt;/code&gt; 函数确定工作目录和沙箱边界，确保所有文件操作都在受控工作区内进行，不对用户系统造成非预期修改。&lt;/p&gt;&#xA;&lt;h3&gt;9.2 加载技能与上下文文件&lt;/h3&gt;&#xA;&lt;p&gt;加载当前智能体可用的所有技能和上下文文件。&lt;/p&gt;&#xA;&lt;h3&gt;9.3 创建工具集&lt;/h3&gt;&#xA;&lt;p&gt;执行 &lt;code&gt;createOpenClawCodingTools&lt;/code&gt; 函数，创建智能体可以使用的所有工具：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;OpenClaw 自研工具&lt;/strong&gt;：&lt;code&gt;exec&lt;/code&gt;（执行命令）、&lt;code&gt;process&lt;/code&gt;（管理后台进程）、&lt;code&gt;apply_patch&lt;/code&gt;（应用代码补丁）等&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Pi SDK 提供的工具&lt;/strong&gt;：&lt;code&gt;read&lt;/code&gt;（读取文件）、&lt;code&gt;write&lt;/code&gt;（写入文件）、&lt;code&gt;edit&lt;/code&gt;（编辑文件）、&lt;code&gt;grep&lt;/code&gt;（内容搜索）等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/ff61343d76933c2d7bc01a13db87a2554514e0d0/src/agents/pi-embedded-runner/system-prompt.ts&#34;&gt;9.4 构建系统提示词&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;buildEmbeddedSystemPrompt&lt;/code&gt; 和 &lt;code&gt;buildAgentSystemPrompt&lt;/code&gt; 函数，读取大量运行时环境信息，拼接成一个非常长的结构化系统提示词——包括所有技能文档、项目说明文档、架构文档、灵魂设定文档，甚至每日生成的记忆文件。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;大模型获得了更完整的环境信息，但也会消耗巨量 token；上下文过长时，反而会稀释模型注意力，导致抓不住核心需求，甚至触发上下文窗口溢出。&lt;strong&gt;这是 OpenClaw token 消耗过快、偶尔出现幻觉的核心原因之一。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/ec2c6d83b9f5f91d6d9094842e0f19b88e63e3e2/src/agents/pi-embedded-runner/run/attempt.ts#L1836&#34;&gt;9.5 创建智能体会话并发起请求&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;通过 Pi SDK 的 &lt;code&gt;createAgentSession&lt;/code&gt; 函数创建智能体会话，把所有工具、上下文、规则绑定到会话里，再通过 &lt;code&gt;applySystemPromptOverrideToSession&lt;/code&gt; 把系统提示词固定到本次会话。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;最核心的一步&lt;/strong&gt;：通过 &lt;code&gt;activeSession.agent.streamFn&lt;/code&gt; 建立流式请求函数，调用 &lt;code&gt;activeSession.prompt(effectivePrompt)&lt;/code&gt; 真正向大模型发送请求。&lt;/p&gt;&#xA;&lt;p&gt;Pi SDK 负责管理整个 &lt;strong&gt;Agent Loop&lt;/strong&gt;（智能体执行循环）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;模型生成文本内容&lt;/li&gt;&#xA;&lt;li&gt;触发工具调用&lt;/li&gt;&#xA;&lt;li&gt;接收工具返回结果&lt;/li&gt;&#xA;&lt;li&gt;把工具结果写回会话历史&lt;/li&gt;&#xA;&lt;li&gt;继续下一轮推理生成&lt;/li&gt;&#xA;&lt;li&gt;循环直到任务完成&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3&gt;&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/87c4ae36b4ccbcac25ceb238ef357297761f4bdc/src/agents/pi-embedded-runner/run/attempt.ts#L2214&#34;&gt;9.6 流式分发&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;因为是流式生成，模型会逐段输出内容，系统通过 &lt;code&gt;subscribeEmbeddedPiSession&lt;/code&gt; 订阅会话里的所有事件，在流式输出过程中触发 &lt;code&gt;onPartialReply&lt;/code&gt;、&lt;code&gt;onBlockReply&lt;/code&gt; 等回调函数，把每一段刚生成的内容立刻推送给前端消息渠道。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;这就是我们在聊天窗口看到的&amp;quot;打字机效果&amp;quot;的底层实现&lt;/strong&gt;：事件订阅 + 块级流式分发机制。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/03/15/171007.png&#34; alt=&#34;Agent Loop 执行循环&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;第十层：回复分发与发送&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;源文件：&lt;a href=&#34;https://github.com/openclaw/openclaw/blob/87c4ae36b4ccbcac25ceb238ef357297761f4bdc/extensions/whatsapp/src/auto-reply/monitor/process-message.ts&#34;&gt;&lt;code&gt;extensions/whatsapp/src/auto-reply/monitor/process-message.ts&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;核心函数：&lt;code&gt;dispatchReplyWithBufferedBlockDispatcher&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;最后一步：接收 AI 已经生成好的回复内容，按照合适的方式发送回对应的聊天平台。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;replyresolver&lt;/code&gt;&lt;/strong&gt;：接收来自智能体运行层的所有结果（文本内容、工具调用信息、内容块 ID 等），转换成最终可以发送的回复结构&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;deliverWebReply&lt;/code&gt;&lt;/strong&gt;：根据当前使用的渠道（WhatsApp、Telegram 等），调用对应的平台接口，把整理好的回复内容推送给用户&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;在流式回复场景下，系统接收到每一段完整内容后就立刻发送出去，所以我们看到的回复是一段一段逐渐出现的，而不是等待很久后一次性显示完整答案。&lt;/p&gt;&#xA;&lt;p&gt;当所有内容发送完成，这一轮的消息处理流程&lt;strong&gt;正式结束&lt;/strong&gt;，整个系统回到初始监听状态，等待下一条用户消息。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;总结：OpenClaw 的四个核心特质&lt;/h2&gt;&#xA;&lt;p&gt;经过以上十层的完整拆解，我们可以提炼出 OpenClaw 的四个核心特质：&lt;/p&gt;&#xA;&lt;h3&gt;1. 运行时装配体系&lt;/h3&gt;&#xA;&lt;p&gt;OpenClaw 最核心的价值，在于构建了一套完整的运行时装配体系，能把用户的一条消息精准嵌入到一个全维度的运行环境里。&lt;/p&gt;&#xA;&lt;h3&gt;2. 不生产智能，只搭建舞台&lt;/h3&gt;&#xA;&lt;p&gt;OpenClaw 本身并不生产智能——它把核心的智能生成任务完整交给了外部的 Pi SDK，自己却完成了鉴权校验、文件读写、工具管理、上下文装配、会话调度、渠道适配、异常处理等所有的&amp;quot;脏活累活&amp;quot;，最后把整理好的数据喂给大模型的 SDK。&lt;/p&gt;&#xA;&lt;h3&gt;3. 提示词工程的极致实践&lt;/h3&gt;&#xA;&lt;p&gt;OpenClaw 把所有的运行时信息，全部显式地、结构化地翻译进了系统提示词里，是提示词工程做到极致的典型案例。&lt;/p&gt;&#xA;&lt;h3&gt;4. 本地优先的消息系统网关&lt;/h3&gt;&#xA;&lt;p&gt;从架构上看，OpenClaw 的前端对接了大量消息渠道，中间是统一的控制平面，底层挂载了智能体运行时、工具集、CLI 交互界面、记忆系统等。&lt;strong&gt;网关才是整个系统的控制平面，本质上它是一个网关系统。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;完整流程一览&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code&gt;用户发送消息&#xA;    ↓&#xA;[第一层] 网关启动与初始化 (monitor.ts)&#xA;    ↓&#xA;[第二层] 消息接入与标准化 (inbound/monitor.ts)&#xA;         去重 → 权限校验 → 媒体下载 → 封装为 WebInboundMessage → 防抖队列&#xA;    ↓&#xA;[第三层] 消息路由与智能体分发 (on-message.ts)&#xA;         动态配置 → 方向解析 → resolveAgentRoute → 会话键值 → 安全检查&#xA;    ↓&#xA;[第四层] 推理环境准备 (get-reply.ts)&#xA;         确认智能体 → 工作目录 → 媒体解析 → 加载历史 → 解析指令&#xA;    ↓&#xA;[第五层] 执行参数转换 (get-reply-run.ts)&#xA;         提示词结构化 → 运行配置调整 → 消息队列排序&#xA;    ↓&#xA;[第六层] 生命周期调度 (agent-runner.ts)&#xA;         入队 → 记忆压缩持久化 → 触发 runAgentTurnWithFallback&#xA;    ↓&#xA;[第七层] 执行容错与降级 (agent-runner-execution.ts)&#xA;         UUID 注册 → 失败重试 → 降级切换 → CLI/嵌入式路径选择&#xA;    ↓&#xA;[第八层] 嵌入式智能体准备 (pi-embedded-runner/run.ts)&#xA;         排队规则 → 输出格式 → 模型补全 → 多密钥轮询&#xA;    ↓&#xA;[第九层] Agent Loop 执行循环 (run/attempt.ts)&#xA;         沙箱环境 → 工具集 → 系统提示词构建 → 创建会话 → 发起请求&#xA;         ↕ (工具调用 ↔ 推理生成，循环直到任务完成)&#xA;    ↓&#xA;[第十层] 回复分发与发送 (process-message.ts)&#xA;         结果整理 → 格式适配 → 推送到即时通讯平台&#xA;    ↓&#xA;用户看到回复&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;hr /&gt;&#xA;&lt;p&gt;&lt;em&gt;理解了这套完整的执行链路，你会发现 OpenClaw 真正厉害的地方，不在于它调用了多么先进的 AI 模型，而在于它用工程化的方式，把&amp;quot;让 AI 真正可用于生产环境&amp;quot;这件事，做得非常扎实。&lt;/em&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2026/2026-03-15-openclaw-source-analysis/</guid>
    </item>
    <item>
      <title>Java Static Inner Class</title>
      <link>https://blog.yuhaowin.com/2026/2026-02-12-java-static-inner-class/</link>
      <description>&lt;h1&gt;Java Static Inner Class&lt;/h1&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;java.lang.reflect.Field&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Outer&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Inner&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;StaticInner&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Inner fields:&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;Field f &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; Inner&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getDeclaredFields&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;())&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;  &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; f&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getName&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34; : &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; f&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getType&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;());&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;StaticInner fields:&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;Field f &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; StaticInner&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getDeclaredFields&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;())&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;  &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; f&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getName&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34; : &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; f&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getType&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;());&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;运行结果：&lt;/h4&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Inner fields:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  this$0 : class Outer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;StaticInner fields:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;结论：&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Java 的静态内部类（Static Inner Class）不会隐式地持有对外部类实例的引用，因此它没有 &lt;code&gt;this$0&lt;/code&gt; 字段。&lt;/li&gt;&#xA;&lt;li&gt;非静态内部类（Inner Class）会隐式地持有对外部类实例的引用，因此它有一个 &lt;code&gt;this$0&lt;/code&gt; 字段，指向外部类的实例。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2026/2026-02-12-java-static-inner-class/</guid>
    </item>
    <item>
      <title>当我们谈论 Agent Infra 时，我们到底在谈什么？</title>
      <link>https://blog.yuhaowin.com/2026/2026-01-31-agent-infra/</link>
      <description>&lt;h1&gt;当我们谈论 Agent Infra 时，我们到底在谈什么？&lt;/h1&gt;&#xA;&lt;h2&gt;目录&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E5%BC%95%E8%A8%80&#34;&gt;引言&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E8%BF%99%E7%AF%87%E6%96%87%E7%AB%A0%E4%B8%8D%E8%AE%A8%E8%AE%BA%E4%BB%80%E4%B9%88&#34;&gt;这篇文章不讨论什么&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E5%BD%93%E5%89%8D%E9%BB%98%E8%AE%A4%E7%9A%84-agent-%E6%9E%B6%E6%9E%84&#34;&gt;当前默认的 Agent 架构&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E5%BD%93%E5%89%8D%E6%9E%B6%E6%9E%84%E7%9A%84%E9%97%AE%E9%A2%98&#34;&gt;当前架构的问题&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%E6%98%AF%E5%A4%A9%E7%84%B6%E7%93%B6%E9%A2%88&#34;&gt;顺序执行是天然瓶颈&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#agent-%E5%8D%8F%E4%BD%9C%E7%9A%84%E6%9E%81%E9%99%90&#34;&gt;Agent 协作的极限&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E9%95%BF%E6%97%B6%E9%97%B4%E4%BB%BB%E5%8A%A1%E4%B8%AD%E7%9A%84%E7%8E%AF%E5%A2%83%E9%80%80%E5%8C%96&#34;&gt;长时间任务中的环境退化&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E9%80%9A%E5%BE%80%E7%89%A9%E7%90%86%E4%B8%96%E7%95%8C%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%80%E5%85%AC%E9%87%8C&#34;&gt;通往物理世界的&amp;quot;最后一公里&amp;quot;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E4%B8%80%E4%B8%AA%E5%8F%AF%E8%83%BD%E7%9A%84%E6%96%B9%E5%90%91box-%E6%8A%BD%E8%B1%A1&#34;&gt;一个可能的方向：Box 抽象&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E9%97%AE%E9%A2%98%E7%9A%84%E6%97%A2%E8%A7%86%E6%84%9F&#34;&gt;问题的既视感&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E5%BC%95%E5%85%A5-box&#34;&gt;引入 Box&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E4%BB%8E%E7%BC%96%E7%A0%81%E5%88%B0%E7%89%A9%E7%90%86%E4%B8%96%E7%95%8C&#34;&gt;从编码到物理世界&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#agent-%E7%9A%84-kubernetes&#34;&gt;Agent 的 Kubernetes&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#%E7%BB%93%E8%AF%AD&#34;&gt;结语&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;引言&lt;/h2&gt;&#xA;&lt;p&gt;Agent 基础设施毫无疑问是当下 VC 投资中最火热的方向之一。我个人也在这个领域下注——但与大多数 VC 不同的是，我是以基础设施使用者和构建者的身份进入这个领域的。正因如此，我想从一个经常被忽视、却非常基础的问题出发：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;当我们谈论 Agent Infra 时，我们到底在谈什么？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;这篇文章不讨论什么&lt;/h2&gt;&#xA;&lt;p&gt;首先，先划清边界。这篇文章不是在讨论通用 AI 基础设施——无论是预训练、后训练 RL，还是推理基础设施。这些都不在本文的讨论范围内，说实话，我对它们兴趣也不大。&lt;/p&gt;&#xA;&lt;p&gt;这些系统大多服务于训练流程，不管是预训练还是 RL。模型训练本质上是一次性或按代进行的活动，这意味着围绕它构建的许多支撑系统天生就是&amp;quot;可丢弃&amp;quot;的。&lt;/p&gt;&#xA;&lt;p&gt;而推理基础设施则已经高度商品化，在产品层面几乎没有太多创新空间。&lt;/p&gt;&#xA;&lt;h3&gt;真正的机遇&lt;/h3&gt;&#xA;&lt;p&gt;真正让我感兴趣的是：&lt;strong&gt;推理基础设施之上的东西&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;随着 Agent 开始接管越来越多的工作，我相信在&amp;quot;推理之上、Agent 之下&amp;quot;，会出现一个全新的基础设施层——一个专门为 Agent 的执行与协作而设计的运行时层。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;当前默认的 Agent 架构&lt;/h2&gt;&#xA;&lt;p&gt;我们先对齐一下大多数人心中&amp;quot;默认&amp;quot;的 Agent 架构。一个典型的 Agent 系统通常包含以下组件：&lt;/p&gt;&#xA;&lt;h3&gt;五个核心组件&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;LLM / 推理核心&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;负责理解上下文、生成计划、决定下一步行动&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Planner / Executor（规划器 / 执行器）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;将复杂目标拆解为步骤，并逐步执行&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Tools / Skills（工具 / 技能）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;封装的外部能力，例如调用 API、执行代码、访问数据库、浏览网页等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Memory / Context Store（记忆 / 上下文存储）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;存储中间状态、历史行为、长期偏好等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Environment（环境，通常是隐式的）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;动作被执行的真实或虚拟世界&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3&gt;Agentic Loop&lt;/h3&gt;&#xA;&lt;p&gt;这些组件运行在一个持续循环中——也就是 &lt;strong&gt;Agentic Loop&lt;/strong&gt;，这几乎是当今所有 Agent 所采用的架构。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/02/01/201405.png&#34; alt=&#34;Agent默认架构&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;当前架构的问题&lt;/h2&gt;&#xA;&lt;p&gt;虽然这个架构在概念上清晰，但在实践中存在多个关键瓶颈，限制了 Agent 系统的能力和效率。&lt;/p&gt;&#xA;&lt;h3&gt;顺序执行是天然瓶颈&lt;/h3&gt;&#xA;&lt;p&gt;我之前已经写过相关内容。即使规划是完美的，大多数 Agent 仍然按如下方式执行任务：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;一步 → 等结果 → 下一步&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;这是一个高度顺序化的执行模型。即便使用了子 Agent，任务分发的粒度也通常非常小。&lt;/p&gt;&#xA;&lt;h4&gt;问题表现&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;动作之间的强依赖使并行几乎不可能&lt;/li&gt;&#xA;&lt;li&gt;任意一步失败都会阻塞整个执行路径&lt;/li&gt;&#xA;&lt;li&gt;对探索型任务极其低效&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4&gt;关键洞察&lt;/h4&gt;&#xA;&lt;p&gt;我强烈直觉认为：&lt;strong&gt;大规模探索是解决真正复杂任务的关键&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;举个例子，在我优化 Coding Agent 工作流时，目标是让 Agent 在尽可能长的时间内自主运行、无需人工干预。但&amp;quot;没有方向的自主&amp;quot;是毫无意义的，真正的关键在于：让 Agent 能持续探索多种可能性、总结结果、并迭代改进。&lt;/p&gt;&#xA;&lt;p&gt;如果探索本身是低效的，整体吞吐和质量都会迅速崩溃。&lt;/p&gt;&#xA;&lt;h3&gt;Agent 协作的极限&lt;/h3&gt;&#xA;&lt;p&gt;我们已经见过许多 Agent 协作的尝试：通信协议、协调框架、多 Agent 系统。MCP、A2A 是其中比较有代表性的例子——但它们都谈不上真正成功。&lt;/p&gt;&#xA;&lt;p&gt;今天的 Agent 协作，更像是&amp;quot;勉强能对话的 Agent&amp;quot;，离真正的协作还差得很远。&lt;/p&gt;&#xA;&lt;h4&gt;协议的局限&lt;/h4&gt;&#xA;&lt;p&gt;当然，人们在积极推动 A2A 类方案，想法本身也没错：Agent 应该能委派任务、汇报进度、动态协作。&lt;/p&gt;&#xA;&lt;p&gt;问题在于：&lt;strong&gt;协议本身并不够&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;A2A 只是定义了&amp;quot;应该发生什么&amp;quot;，却没有回答&amp;quot;如何构建一个真正可用的系统，让这些事情真的发生&amp;quot;。中间仍然缺失一个关键层，而到目前为止，还没有一个真正可用的平台。&lt;/p&gt;&#xA;&lt;h3&gt;长时间任务中的环境退化&lt;/h3&gt;&#xA;&lt;p&gt;还有一个我认为极其重要、却被严重低估的问题。&lt;/p&gt;&#xA;&lt;p&gt;如果你的系统无法提供原子化、无副作用的动作，那么在复杂任务执行过程中，环境几乎必然会逐步退化。&lt;/p&gt;&#xA;&lt;h4&gt;问题的根源&lt;/h4&gt;&#xA;&lt;p&gt;这在 Demo 中并不明显。但在任何长链路、多步骤、探索型工作流中，几乎是必然发生的。&lt;/p&gt;&#xA;&lt;p&gt;现实世界中的大多数动作都具有强副作用。一旦第一个动作执行，环境就已经被&amp;quot;污染&amp;quot;了。随着动作不断叠加，状态累积、错误放大、失败路径与成功路径交织在一起，最终 Agent 根本无法判断当前环境真实处于什么状态。&lt;/p&gt;&#xA;&lt;p&gt;到那时，无论规划器多聪明、推理能力多强，Agent 都是在一个不断腐化的环境中做决策。&lt;/p&gt;&#xA;&lt;h4&gt;现实案例：Coding Agent&lt;/h4&gt;&#xA;&lt;p&gt;Coding Agent 是最典型的例子。把它们放进一个真实的大型代码库，很快就会出现同样的模式：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;工作区变得混乱&lt;/li&gt;&#xA;&lt;li&gt;随机的 Markdown 文件到处都是&lt;/li&gt;&#xA;&lt;li&gt;日志风格不统一&lt;/li&gt;&#xA;&lt;li&gt;临时代码没人清理&lt;/li&gt;&#xA;&lt;li&gt;多个子 Agent 在同一目录互相覆盖修改&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这就是环境退化的教科书案例。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/02/01/201438.png&#34; alt=&#34;工作区环境退化过程&#34; /&gt;&lt;/p&gt;&#xA;&lt;h4&gt;现有的变通方案：Git Worktree&lt;/h4&gt;&#xA;&lt;p&gt;工程师们已经找到了一种粗糙但有效的变通方案：&lt;strong&gt;Git worktree&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;每个子 Agent 拥有一个隔离的 worktree，在最小化的环境中完成任务，只通过 diff 或 PR 的形式返回结果。&lt;/p&gt;&#xA;&lt;p&gt;本质上，这是一种低成本的方式，用来提供隔离、可丢弃的执行环境。它很接近正确答案，但它无法规模化，也无法泛化。&lt;/p&gt;&#xA;&lt;h3&gt;通往物理世界的&amp;quot;最后一公里&amp;quot;&lt;/h3&gt;&#xA;&lt;p&gt;表面上看，今天的 Agent 已经很强大了。但一旦你让它们做一些没有干净 API 的事情，一些真正影响现实世界的操作，体验立刻变得脆弱不堪。&lt;/p&gt;&#xA;&lt;p&gt;试着让 Agent 去下单、付款、订酒店。&lt;/p&gt;&#xA;&lt;h4&gt;Skills 的局限&lt;/h4&gt;&#xA;&lt;p&gt;Skills 是一个很好的抽象——我也非常喜欢它。在纯软件场景下，它们表现不错。但一旦任务进入物理世界，这个抽象就开始失效。&lt;/p&gt;&#xA;&lt;p&gt;现实世界充满了隐式状态：登录会话、权限、风控、UI 变化、临时校验、重试机制。人类可以直觉性地处理这些，但它们几乎从未被封装成干净的执行模型。&lt;/p&gt;&#xA;&lt;p&gt;结果是：Agent 的每一步操作都会在环境中留下&amp;quot;残留&amp;quot;，而这些残留又会反过来影响后续规划。&lt;/p&gt;&#xA;&lt;h4&gt;未来展望&lt;/h4&gt;&#xA;&lt;p&gt;我怀疑，Skills 很快会从&amp;quot;软件操作&amp;quot;扩展到诸如&amp;quot;买菜 Skill&amp;quot;&amp;quot;买咖啡 Skill&amp;quot;这类能力。只有这样，Claude Cowork 这样的产品才能真正发挥潜力。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;一个可能的方向：Box 抽象&lt;/h2&gt;&#xA;&lt;h3&gt;问题的既视感&lt;/h3&gt;&#xA;&lt;p&gt;这些问题让我产生了一种强烈的既视感。&lt;/p&gt;&#xA;&lt;p&gt;在过去十多年里，DevOps 和云计算在从单机系统迈向大规模分布式架构时，曾遇到过几乎一模一样的挑战。&lt;/p&gt;&#xA;&lt;p&gt;早期系统不稳定、难以调试、不可复现。在单机上还能勉强应付，一旦到 1000 台机器，状态爆炸就成了致命问题。&lt;/p&gt;&#xA;&lt;p&gt;最初我们责怪人：流程不规范、运维粗心、文档不完整。后来才意识到，真正的问题并不在于人，而在于&lt;strong&gt;缺乏稳定的执行基础&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h4&gt;云计算的解决方案&lt;/h4&gt;&#xA;&lt;p&gt;容器、不可变基础设施、基础设施即代码、声明式配置，并没有让软件更聪明，但它们让环境变得可控：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;失败可复现&lt;/li&gt;&#xA;&lt;li&gt;部署可重复&lt;/li&gt;&#xA;&lt;li&gt;操作可幂等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4&gt;历史的重复&lt;/h4&gt;&#xA;&lt;p&gt;当我今天看 Agent Infra 时，感觉我们正站在同一个拐点上。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Agent 并不缺智能，它们被迫在不稳定、不可预测的环境中工作。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3&gt;引入 Box&lt;/h3&gt;&#xA;&lt;p&gt;我的第一个建议其实很简单：将 Skill 与其执行环境绑定在一起。&lt;/p&gt;&#xA;&lt;p&gt;引入一个新的抽象，我们称之为 &lt;strong&gt;Box&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h4&gt;Box 的定义&lt;/h4&gt;&#xA;&lt;p&gt;一个 Box：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;不暴露任何执行细节&lt;/li&gt;&#xA;&lt;li&gt;没有外部依赖&lt;/li&gt;&#xA;&lt;li&gt;没有副作用&lt;/li&gt;&#xA;&lt;li&gt;封装了 Skill 引导的动作 + 可复现、可丢弃的环境&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Box 解决的是单一环境内的执行质量问题。由于它是由 Skill 定义的，因此可以组合、继承。&lt;/p&gt;&#xA;&lt;h4&gt;实际例子&lt;/h4&gt;&#xA;&lt;p&gt;例如，&amp;quot;给我买一杯咖啡&amp;quot;可以拆解为原子级 Skills：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;打开浏览器 → Box1&lt;/li&gt;&#xA;&lt;li&gt;登录我的账号 → Box2&lt;/li&gt;&#xA;&lt;li&gt;下单买咖啡 → Box3&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这些可以组合成一个 &amp;quot;Buy Coffee&amp;quot; Box，前两个 Box 甚至可以被缓存。&lt;/p&gt;&#xA;&lt;p&gt;Claude 只需要写：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;box3 &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; box1 &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; box2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;box3&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;spawn()&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;buy_coffee(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;latte&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;咖啡买完后，Box 被销毁——本地环境不会被污染。&lt;/p&gt;&#xA;&lt;h4&gt;Box vs Docker&lt;/h4&gt;&#xA;&lt;p&gt;与 Docker 不同，Box 的环境是纯粹的、轻量的、完全语义化的，没有任何技术细节向上泄漏。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/02/01/201515.svg&#34; alt=&#34;Box抽象：隔离和可组合性&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3&gt;从编码到物理世界&lt;/h3&gt;&#xA;&lt;p&gt;这种方式不仅解决了 Coding Agent 的&amp;quot;最后一公里&amp;quot;问题，还能走得更远——它弥合了代码与现实世界之间的鸿沟。&lt;/p&gt;&#xA;&lt;p&gt;对于&amp;quot;买咖啡&amp;quot;&amp;quot;找并预订最便宜的酒店&amp;quot;这类任务，等待 API 出现并不现实。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Box 是一次尝试：把物理世界编码化。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;一旦我们拥有足够多的 Box 函数，编程现实世界将变成 Agent 最擅长的事情。&lt;/p&gt;&#xA;&lt;h4&gt;已有的探索&lt;/h4&gt;&#xA;&lt;p&gt;已经有一些前沿创业公司在探索类似方向，例如：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/boxlite-ai/boxlite&#34;&gt;https://github.com/boxlite-ai/boxlite&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/vm0-ai/vm0&#34;&gt;https://github.com/vm0-ai/vm0&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;Agent 的 Kubernetes&lt;/h2&gt;&#xA;&lt;p&gt;如果每个动作都运行在可复现、可丢弃的 Box 中，下一个问题几乎是必然的：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;谁来创建 Box？&lt;/li&gt;&#xA;&lt;li&gt;谁来调度它们？&lt;/li&gt;&#xA;&lt;li&gt;谁来监控它们？&lt;/li&gt;&#xA;&lt;li&gt;谁来决定重试、放弃，还是分叉执行路径？&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;答案再次来自云基础设施。&lt;/p&gt;&#xA;&lt;p&gt;Kubernetes 成为了容器编排的事实标准。那么，&lt;strong&gt;Agent 的 Kubernetes 会是什么样？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3&gt;理想的基础设施层&lt;/h3&gt;&#xA;&lt;p&gt;我认为它应该是一个与模型无关的基础设施层，包含以下组件：&lt;/p&gt;&#xA;&lt;h4&gt;1. Context Manager（上下文管理器）&lt;/h4&gt;&#xA;&lt;p&gt;基于分布式数据库和分布式文件系统。数据库管理结构化的共享上下文（如对话历史，用于 prompt 构造），文件系统则提供 Agent 工作区之外的协作空间。&lt;/p&gt;&#xA;&lt;h4&gt;2. 一等公民的&amp;quot;分支&amp;quot;能力&lt;/h4&gt;&#xA;&lt;p&gt;这不是 Git 分支或 worktree，而是系统级的执行分支机制。多个 Agent（或同一个 Agent）可以在共享目标的前提下，同时探索不同路径，且互不产生副作用。&lt;/p&gt;&#xA;&lt;p&gt;元数据由数据库管理，分支文件系统提供底层支撑。&lt;/p&gt;&#xA;&lt;h4&gt;3. 网络内消息 / 通信枢纽&lt;/h4&gt;&#xA;&lt;p&gt;嵌入到每个 Box 运行时中：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;box1&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;send_message(box2, &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;box1&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;publish_event(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;buy_coffee_success&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;box2&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;on_event(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;buy_coffee_success&amp;#39;&lt;/span&gt;, on_success)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;4. 调度器 + 生命周期管理器&lt;/h4&gt;&#xA;&lt;p&gt;负责资源放置、并发控制、重试、超时、取消以及失败策略。&lt;/p&gt;&#xA;&lt;p&gt;在容器世界里，Kubernetes 每天都在做这些事；而在 Agent 系统中，大多数团队仍然把这些逻辑硬编码进框架里，反复造轮子，可靠性却参差不齐。&lt;/p&gt;&#xA;&lt;h4&gt;5. Box Runtime&lt;/h4&gt;&#xA;&lt;p&gt;也就是前面描述的执行环境。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2026/02/01/201540.png&#34; alt=&#34;Agent Kubernetes架构：5层基础设施栈&#34; /&gt;&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h2&gt;结语&lt;/h2&gt;&#xA;&lt;p&gt;到这个阶段，我认为已经没必要再反复强调模型会变得多么聪明。&lt;/p&gt;&#xA;&lt;p&gt;决定 Agent 能否胜任复杂任务的，并不仅仅是智能水平，而是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;执行是否可控&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;失败是否廉价&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;环境是否可替换&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;协作是否由基础设施保障&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;借鉴历史&lt;/h3&gt;&#xA;&lt;p&gt;Agent Infra 面临的挑战并不新。我们在其他领域已经遇到过，也部分解决过。&lt;/p&gt;&#xA;&lt;p&gt;现在剩下的，是将这些经验重新组织，并应用到这个新的运行时层之上——&lt;strong&gt;Agent Runtime&lt;/strong&gt;。&lt;/p&gt;&#xA;</description>
      <pubDate>Sat, 31 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2026/2026-01-31-agent-infra/</guid>
    </item>
    <item>
      <title>深分页（deep pagination）在 MySQL 的应对策略</title>
      <link>https://blog.yuhaowin.com/2025/2025-11-11-keyset-pagination/</link>
      <description>&lt;h1&gt;深分页（deep pagination）在 MySQL 的应对策略&lt;/h1&gt;&#xA;&lt;p&gt;Keyset Pagination（也叫 Seek / 游标分页）&#xA;原理：不使用 OFFSET，而用已知的“最后一条记录的排序键”做 WHERE 过滤（比如自增主键、时间戳或组合索引），做索引查找，效率非常高。&lt;/p&gt;&#xA;&lt;p&gt;示例（倒序按 created_at + id 唯一确定顺序）&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;-- 首次请求（第一页）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;SELECT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;title,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;created_at&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;posts&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;WHERE&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;status&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;published&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;ORDER&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;BY&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;created_at&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;DESC&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;DESC&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;LIMIT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;20&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;-- 之后请求（把上次最后一条的 (created_at_last, id_last) 作为游标）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;SELECT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;title,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;created_at&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;posts&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;WHERE&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;status&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;published&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;AND&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(created_at&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;2025-11-11 12:34:56&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;       &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;OR&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(created_at&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;2025-11-11 12:34:56&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;AND&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;12345&lt;/span&gt;))&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;ORDER&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;BY&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;created_at&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;DESC&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;DESC&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;LIMIT&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;20&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;也可用行比较（MySQL 支持）：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;AND&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(created_at,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;id)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;2025-11-11 12:34:56&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;12345&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;优点：速度快、稳定，适合实时滚动（如“下一页/上一页”或无限滚动）。&#xA;缺点：无法直接跳到任意第 N 页（比如用户输入页码 10000），需要“游标 / token”支持或预计算索引。&lt;/p&gt;&#xA;&lt;p&gt;实践建议：&#xA;•&#x9;对排序字段建立覆盖索引（如 INDEX(status, created_at, id)），避免回表。&#xA;•&#x9;用 opaque cursor（例如 base64 编码的 created_at|id）在前后端传递，而不是明文 id。&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.cnblogs.com/pDJJq/p/18876878/how-to-do-pagination-z1bs5pm&#34;&gt;https://www.cnblogs.com/pDJJq/p/18876878/how-to-do-pagination-z1bs5pm&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;keyset(seek) pagination vs offset pagination&#xA;Keyset 就是指前一页最后一条的 (created_at, id), 用这一组 key 来决定下一页从哪里继续。&#xA;Seek 表示“从某个位置开始查找”&lt;/p&gt;&#xA;</description>
      <pubDate>Tue, 11 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2025/2025-11-11-keyset-pagination/</guid>
    </item>
    <item>
      <title>acme.sh and nginx</title>
      <link>https://blog.yuhaowin.com/2024/2024-12-01-acme.sh-and-nginx/</link>
      <description>&lt;h1&gt;acme.sh and nginx&lt;/h1&gt;&#xA;&lt;h3&gt;配置 DNSPod API Key&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;DP_Id&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;539918&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;DP_Key&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;d979904a961294da0e797669b7c18f9d&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;颁发证书&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acme.sh --issue --dns dns_dp -d yuhaowin.com -d *.yuhaowin.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;部署证书到七牛云&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;QINIU_AK&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;_woYoRMBoiC_qRYOmaB4ukjAOS7tPYhrzJS-wf82&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;QINIU_SK&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;WOtu_RHHWgUpSyDj-GSz98tl1Qo_5Kg89fsr6azm&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;QINIU_CDN_DOMAIN&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;.yuhaowin.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acme.sh --deploy -d yuhaowin.com --deploy-hook qiniu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;部署证书到本地 nginx&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acme.sh --install-cert -d yuhaowin.com &lt;span style=&#34;color:#d14&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;--key-file       /home/ubuntu/app/nginx/cert/yuhaowin.com/yuhaowin.com.key  &lt;span style=&#34;color:#d14&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;--fullchain-file /home/ubuntu/app/nginx/cert/yuhaowin.com/fullchain.cer &lt;span style=&#34;color:#d14&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;--reloadcmd     &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;docker restart nginx&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sun, 01 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2024/2024-12-01-acme.sh-and-nginx/</guid>
    </item>
    <item>
      <title>java record class feature</title>
      <link>https://blog.yuhaowin.com/2024/2024-10-21-java-record-feature/</link>
      <description>&lt;h1&gt;java record class feature&lt;/h1&gt;&#xA;&lt;h2&gt;使用 jackson 反序列化 record 类型遇到的问题&lt;/h2&gt;&#xA;&lt;h3&gt;定义一个 record 类&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;包含两个组件(字段), 一个是基本类型 age, 一个是集合类型 nickNames。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上述代码没有声明构造器，java 编译器会自动生成一个标准构造器，参数是 age 和 nickNames。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// java 编译器会自动生成一个标准构造器&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;通过 jackson 反序列化 json 字符串到 Person 类型对象。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json5&#34;&gt;{&#xA;  &amp;quot;age&amp;quot;: 18,&#xA;  &amp;quot;nick_names&amp;quot;: [&#xA;    &amp;quot;Tom&amp;quot;,&#xA;    &amp;quot;Jerry&amp;quot;&#xA;  ]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3&gt;问题 1&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;通过 jackson 反序列化 json 字符串到 Person 类型对象时，遇到如下异常。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; Exception &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Exception in thread &amp;#34;main&amp;#34; com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field &amp;#34;nick_names&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是因为 jackson 默认使用驼峰命名法，而 json 字符串中的字段是下划线命名法，所以需要在 record 类中使用 @JsonProperty 注解。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; Exception &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样会生成一个标准构造器。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// java 编译器会自动生成一个标准构造器&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;对 nickNames 字段进行校验&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;使用简化构造器（Compact Constructor）对 nickNames 字段进行校验，如果为 null，则初始化为一个空的集合。&#xA;这种构造器可以省略构造器参数列表，直接在构造器主体中编写逻辑。编译器会自动推断出所有定义的字段，并进行赋值。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 使用简化构造器对 nickNames 字段进行校验&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; Person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;Objects&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;isNull&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            nickNames &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;of&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; Exception &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上述简化构造编译后等价于下面代码实现&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 上述简化构造编译后等价于下面的标准构造器&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;Objects&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;isNull&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            nickNames &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;of&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样我们也开始手动实现一个标准构造器，标准构造器。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 手动实现标准构造器，对 nickNames 字段进行校验&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; Objects&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;isNull&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;?&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;of&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; Exception &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;需要注意的是，手动实现的标准构造器的 nickNames 字段必须用 @JsonProperty(&amp;quot;nick_names&amp;quot;) 修饰。不然会出现一下错误。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// nickNames 字段没有使用 @JsonProperty(&amp;#34;nick_names&amp;#34;) 修饰，导致反序列化失败&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; Objects&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;isNull&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;?&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;of&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; Exception &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person person &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                  &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Exception in thread &amp;#34;main&amp;#34; com.fasterxml.jackson.databind.JsonMappingException: Can not set final java.util.List field com.wosai.crm.qa.Person.nickNames to java.util.ArrayList&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是因为 jackson 无法通过构造器完成 Person 对象的反序列化，构造器参数 nickNames 无法和 nick_names 对应，然后使用反射机制直接修改了&#xA;nickNames 字段，而 nickNames 字段是 final 的，所以会抛出异常。&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h3&gt;问题 2&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;如果使用普通类代替 record 类，需要使用 @JsonCreator 修改构造器和使用 @JsonProperty 修饰构造器参数。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Person&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;final&lt;/span&gt; Long age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;final&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 使用 @JsonCreator 修改构造器和使用 @JsonProperty 修饰构造器参数。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonCreator&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;Person&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; Long age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#3c5d5d;font-weight:bold&#34;&gt;@JsonProperty&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;nick_names&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; List&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; age&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;nickNames&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; nickNames&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; JsonProcessingException &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ObjectMapper mapper &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ObjectMapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person metaData &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;readValue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                   &amp;#34;&lt;/span&gt;age&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: 18,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                   &amp;#34;&lt;/span&gt;nick_names&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;: [&amp;#34;&lt;/span&gt;Tom&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;Jerry&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                 }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d14&#34;&gt;                &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; Person&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;mapper&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;metaData&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;hr /&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/395&#34;&gt;JEP 395: Records&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/21920367/why-when-a-constructor-is-annotated-with-jsoncreator-its-arguments-must-be-ann&#34;&gt;Why when a constructor is annotated with @JsonCreator, its arguments must be annotated with @JsonProperty?&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <pubDate>Mon, 21 Oct 2024 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2024/2024-10-21-java-record-feature/</guid>
    </item>
    <item>
      <title>http 接口偶然响应慢问题排查</title>
      <link>https://blog.yuhaowin.com/2024/2024-08-05-solved-api-slow-problem/</link>
      <description>&lt;h2&gt;http 接口偶然响应慢问题排查&lt;/h2&gt;&#xA;&lt;p&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y tcpdump hping3 mtr traceroute iputils-ping --no-install-recommends tcpdump hping3 mtr&lt;/p&gt;&#xA;&lt;p&gt;tcpdump -i eth0 host api.dify.ai -w capture.pcap&lt;/p&gt;&#xA;&lt;p&gt;kubectl cp crm-qa-12579-7ff6459456-rzzz6:/app/bin/capture.pcap ~/Desktop/crm-qa.pcap&lt;/p&gt;&#xA;&lt;p&gt;curl --location &#39;https://api.dify.ai/v1/chat-messages&#39; &lt;br /&gt;&#xA;--header &#39;Content-Type: application/json&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39; &lt;br /&gt;&#xA;--data &#39;{&#xA;&amp;quot;query&amp;quot;: &amp;quot;拉卡拉校园食堂开通分账业务审批填写规范&amp;quot;,&#xA;&amp;quot;response_mode&amp;quot;: &amp;quot;streaming&amp;quot;,&#xA;&amp;quot;user&amp;quot;: &amp;quot;yuhao&amp;quot;,&#xA;&amp;quot;inputs&amp;quot;: {}&#xA;}&#39;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://weiborao.link/docker-traceroute-tcpdump.html&#34;&gt;https://weiborao.link/docker-traceroute-tcpdump.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;curl -o /dev/null -s -w time_namelookup:&amp;quot;\t&amp;quot;%{time_namelookup}&amp;quot;\n&amp;quot;time_connect:&amp;quot;\t\t&amp;quot;%{time_connect}&amp;quot;\n&amp;quot;time_appconnect:&amp;quot;\t&amp;quot;%{time_appconnect}&amp;quot;\n&amp;quot;time_pretransfer:&amp;quot;\t&amp;quot;%{time_pretransfer}&amp;quot;\n&amp;quot;time_starttransfer:&amp;quot;\t&amp;quot;%{time_starttransfer}&amp;quot;\n&amp;quot;time_total:&amp;quot;\t\t&amp;quot;%{time_total}&amp;quot;\n&amp;quot;time_redirect:&amp;quot;\t\t&amp;quot;%{time_redirect}&amp;quot;\n&amp;quot; --location &#39;https://api.dify.ai/v1/chat-messages&#39; &lt;br /&gt;&#xA;--header &#39;Content-Type: application/json&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39; &lt;br /&gt;&#xA;--data &#39;{&#xA;&amp;quot;query&amp;quot;: &amp;quot;拉卡拉校园食堂开通分账业务审批填写规范&amp;quot;,&#xA;&amp;quot;response_mode&amp;quot;: &amp;quot;streaming&amp;quot;,&#xA;&amp;quot;user&amp;quot;: &amp;quot;yuhao&amp;quot;,&#xA;&amp;quot;inputs&amp;quot;: {}&#xA;}&#39;&lt;/p&gt;&#xA;&lt;p&gt;tcpdump   -i lo  port  6310 -w http.pcap&lt;/p&gt;&#xA;&lt;p&gt;tcpdump -i eth0 host sg-dify.wosai-inc.com -w capture.pcap&lt;/p&gt;&#xA;&lt;p&gt;tcpdump -i eth0 host api.dify.ai -w capture.pcap&lt;/p&gt;&#xA;&lt;p&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y traceroute iputils-ping --no-install-recommends tcpdump&lt;/p&gt;&#xA;&lt;p&gt;apt-get install hping3&lt;/p&gt;&#xA;&lt;p&gt;hping3 -S -p 443 -c 100 api.dify.ai&lt;/p&gt;&#xA;&lt;p&gt;kubectl cp crm-qa-base-5799dbd479-kjxcv:/app/bin/capture.pcap ~/Desktop/crm-qa-1.pcap&lt;/p&gt;&#xA;&lt;p&gt;kubectl cp crm-qa-12579-7ff6459456-rzzz6:/opt/jacoco/report/profit-sharing/report.exec ~/Downloads/report.exec&lt;/p&gt;&#xA;&lt;p&gt;curl --location &#39;https://api.dify.ai/v1/chat-messages&#39; &lt;br /&gt;&#xA;--header &#39;Content-Type: application/json&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39; &lt;br /&gt;&#xA;--data &#39;{&#xA;&amp;quot;query&amp;quot;: &amp;quot;拉卡拉校园食堂开通分账业务审批填写规范&amp;quot;,&#xA;&amp;quot;response_mode&amp;quot;: &amp;quot;streaming&amp;quot;,&#xA;&amp;quot;user&amp;quot;: &amp;quot;yuhao&amp;quot;,&#xA;&amp;quot;inputs&amp;quot;: {}&#xA;}&#39;&lt;/p&gt;&#xA;&lt;p&gt;curl -w &amp;quot;总时间: %{time_total}s\n名称解析时间: %{time_namelookup}s\n连接时间: %{time_connect}s\nTLS握手时间: %{time_appconnect}s\n等待时间: %{time_starttransfer}s\n数据传输时间: %{time_total}s\nHTTP状态码: %{http_code}\n&amp;quot; -o /dev/null --location &#39;https://api.dify.ai/v1/chat-messages&#39; &lt;br /&gt;&#xA;--header &#39;Content-Type: application/json&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39; &lt;br /&gt;&#xA;--data &#39;{&#xA;&amp;quot;query&amp;quot;: &amp;quot;拉卡拉校园食堂开通分账业务审批填写规范&amp;quot;,&#xA;&amp;quot;response_mode&amp;quot;: &amp;quot;streaming&amp;quot;,&#xA;&amp;quot;user&amp;quot;: &amp;quot;yuhao&amp;quot;,&#xA;&amp;quot;inputs&amp;quot;: {}&#xA;}&#39;&lt;/p&gt;&#xA;&lt;p&gt;curl -o /dev/null -s -w time_namelookup:&amp;quot;\t&amp;quot;%{time_namelookup}&amp;quot;\n&amp;quot;time_connect:&amp;quot;\t\t&amp;quot;%{time_connect}&amp;quot;\n&amp;quot;time_appconnect:&amp;quot;\t&amp;quot;%{time_appconnect}&amp;quot;\n&amp;quot;time_pretransfer:&amp;quot;\t&amp;quot;%{time_pretransfer}&amp;quot;\n&amp;quot;time_starttransfer:&amp;quot;\t&amp;quot;%{time_starttransfer}&amp;quot;\n&amp;quot;time_total:&amp;quot;\t\t&amp;quot;%{time_total}&amp;quot;\n&amp;quot;time_redirect:&amp;quot;\t\t&amp;quot;%{time_redirect}&amp;quot;\n&amp;quot; --location &#39;http://sg-dify.wosai-inc.com/v1/chat-messages&#39; &lt;br /&gt;&#xA;--header &#39;Content-Type: application/json&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39; &lt;br /&gt;&#xA;--data &#39;{&#xA;&amp;quot;query&amp;quot;: &amp;quot;拉卡拉校园食堂开通分账业务审批填写规范&amp;quot;,&#xA;&amp;quot;response_mode&amp;quot;: &amp;quot;streaming&amp;quot;,&#xA;&amp;quot;user&amp;quot;: &amp;quot;yuhao&amp;quot;,&#xA;&amp;quot;inputs&amp;quot;: {}&#xA;}&#39;&lt;/p&gt;&#xA;&lt;p&gt;curl -o /dev/null -s -w time_namelookup:&amp;quot;\t&amp;quot;%{time_namelookup}&amp;quot;\n&amp;quot;time_connect:&amp;quot;\t\t&amp;quot;%{time_connect}&amp;quot;\n&amp;quot;time_appconnect:&amp;quot;\t&amp;quot;%{time_appconnect}&amp;quot;\n&amp;quot;time_pretransfer:&amp;quot;\t&amp;quot;%{time_pretransfer}&amp;quot;\n&amp;quot;time_starttransfer:&amp;quot;\t&amp;quot;%{time_starttransfer}&amp;quot;\n&amp;quot;time_total:&amp;quot;\t\t&amp;quot;%{time_total}&amp;quot;\n&amp;quot;time_redirect:&amp;quot;\t\t&amp;quot;%{time_redirect}&amp;quot;\n&amp;quot; --location --request GET &#39;https://api.dify.ai/v1/datasets?page=1&amp;amp;limit=20&#39; &lt;br /&gt;&#xA;--header &#39;Authorization: Bearer fake-token&#39;&lt;/p&gt;&#xA;</description>
      <pubDate>Mon, 05 Aug 2024 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2024/2024-08-05-solved-api-slow-problem/</guid>
    </item>
    <item>
      <title>state-machine 状态机</title>
      <link>https://blog.yuhaowin.com/2024/2024-05-12-state-machine/</link>
      <description>&lt;h2&gt;state-machine 状态机&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.cnblogs.com/StarbucksBoy/p/16888787.html&#34;&gt;https://www.cnblogs.com/StarbucksBoy/p/16888787.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://blog.csdn.net/significantfrank/article/details/104996419&#34;&gt;https://blog.csdn.net/significantfrank/article/details/104996419&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://cloud.benym.cn/pages/2ae430/#%E8%83%8C%E6%99%AF&#34;&gt;https://cloud.benym.cn/pages/2ae430/#%E8%83%8C%E6%99%AF&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2024/08/06/175550.PNG&#34; alt=&#34;state-machine&#34; /&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2024/2024-05-12-state-machine/</guid>
    </item>
    <item>
      <title>回车和换行的历史</title>
      <link>https://blog.yuhaowin.com/2023/2023-08-17-carriage-return-and-line-feed/</link>
      <description>&lt;h1&gt;回车和换行的历史&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;quot;回车&amp;quot; 和 &amp;quot;换行&amp;quot; 均是来源机械英文打字机，是两个独立的过程。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2&gt;回车&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;回车的英文是：Carriage Return，回车的意思是回到一行的开头，但并不会换到下一行，只是回到了一行的开头。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;回车中的&amp;quot;车&amp;quot;指的是纸车,带着纸一起左右移动的模块，当开始打第一个字之前，要把纸车拉到最右边，弹簧处于拉伸状态，随着打字弹簧会把纸车往左边拉，每当打完一行后，纸车就完全收回去了，&#xA;当打下一行之前需要重新把纸车拉到最右边，使得指针指向行的开头，所以叫回车。&lt;/p&gt;&#xA;&lt;h2&gt;换行&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;换行的英文是：Line Feed，换行的意思是换到下一行，但并不会回到行的开头，只是换到了下一行的同一位置。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;机械英文打字机左边有个&amp;quot;把手&amp;quot;，往下扳动一下，纸会上移一行，所以叫换行。&lt;/p&gt;&#xA;&lt;h2&gt;回车换行在现代计算机中的表示&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;回车：CR，ASCII 代码是 13，或 0x0D，CR=Carriage Return=/r&lt;/li&gt;&#xA;&lt;li&gt;换行：LF，ASCII 代码是 10，或 0x0A，LF=Line Feed=/n&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2&gt;不同操作系统对行分隔符的不同实现&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;行分隔符，Line Separator，不同操作系统对行分隔符的实现是不同的。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Windows 系统里，行分隔符为 &lt;strong&gt;/r/n&lt;/strong&gt;，每行结尾是 &amp;quot;回车+换行&amp;quot;，即 &amp;quot;CR+LF&amp;quot;，ASCII 码为 0x0D 0x0A&lt;/li&gt;&#xA;&lt;li&gt;Mac 9 以及以前系统里，行分隔符为 &lt;strong&gt;/r&lt;/strong&gt;，即 &amp;quot;CR&amp;quot;，ASCII 码为 0x0D&lt;/li&gt;&#xA;&lt;li&gt;Unix/Linux、Mac X 以及以后系统里，行分隔符为 &lt;strong&gt;/n&lt;/strong&gt;，即 &amp;quot;LF&amp;quot;，ASCII 码为 0x0A&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2&gt;显示文本文件中的行分隔符&lt;/h2&gt;&#xA;&lt;p&gt;在 macOS 终端中，要正确显示文件中的回车换行字符，可以使用如下命令：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat -e filename&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这个命令会将文件的内容显示在终端上，并以可见的方式显示回车换行字符。回车字符会显示为^M，换行字符会显示为$。&lt;/p&gt;&#xA;&lt;p&gt;也可以使用 od 命令，将文件的内容以十六进制形式显示，并显示特殊字符的表示。以下是一个示例命令:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;od -c filename&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这将会以十六进制和字符形式显示文件内容，可以在输出中找到回车换行字符（\r 和 \n）。&lt;/p&gt;&#xA;&lt;h2&gt;常用文本编辑器和 IDE 中行分隔符的设置&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;一般文本编辑器都可以选择使用不同的行分隔符。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Sublime Text&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;View -&amp;gt; Line Endings&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2023/08/17/110302.png&#34; alt=&#34;110302&#34; /&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;JetBrains IDE&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Settings -&amp;gt; Editor -&amp;gt; Code Style -&amp;gt; Line separator&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2023/08/17/110945.png&#34; alt=&#34;110945&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2&gt;reference&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.ruanyifeng.com/blog/2006/04/post_213.html&#34;&gt;回车和换行的故事&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=dz-UifvPF78&#34;&gt;英文机械打字机使用说明&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.jetbrains.com/help/idea/configuring-line-endings-and-line-separators.html&#34;&gt;Configure line separators&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <pubDate>Thu, 17 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2023/2023-08-17-carriage-return-and-line-feed/</guid>
    </item>
    <item>
      <title>closure table</title>
      <link>https://blog.yuhaowin.com/2023/2023-08-03-tree-sql-design/</link>
      <description>&lt;h1&gt;closure table&lt;/h1&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://blog.csdn.net/qq_38011415/article/details/95462698&#34;&gt;https://blog.csdn.net/qq_38011415/article/details/95462698&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://juejin.cn/post/7129023794701828104&#34;&gt;https://juejin.cn/post/7129023794701828104&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Thu, 03 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2023/2023-08-03-tree-sql-design/</guid>
    </item>
    <item>
      <title>MySQL InnoDB Buffer Pool Size 调优</title>
      <link>https://blog.yuhaowin.com/2023/2023-06-06-mysql-innodb-buffer-pool-size/</link>
      <description>&lt;h1&gt;MySQL InnoDB Buffer Pool Size 调优&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;背景：项目提测，发现数据库性能不佳，内存占用并不高，经过排查，发现是数据库的缓存池配置不合理，导致数据库频繁 IO，影响性能。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h3&gt;MySQL 内存分配&lt;/h3&gt;&#xA;&lt;p&gt;MySQL 的内存可以分为 global 级的共享内存和 session 级的私有内存两部分，共享内存是实例启动时分配的是所有连接共享的。&#xA;私有内存用于每个连接到 MySQL 服务器时才分配各自的缓存，一些特殊的 SQL 或字段类型会导致单个线程可能分配多次缓存，因此当出现&#xA;OOM 异常，都是由各个连接私有内存造成的。&lt;/p&gt;&#xA;&lt;h3&gt;InnoDB Buffer Pool&lt;/h3&gt;&#xA;&lt;p&gt;该部分缓存是 InnoDB&#xA;引擎最重要的缓存区域，是通过内存来弥补物理数据文件的重要手段，MySQL &lt;a href=&#34;https://dev.mysql.com/doc/refman/8.0/en/memory-use.html&#34;&gt;参考手册推荐该部分配置为机器内存规格配置的50% - 75%&lt;/a&gt;&#xA;。其中主要包含数据页、索引页、undo 页、insert buffer、自适应哈希索引、锁信息以及数据字典等信息。在进行 SQL&#xA;读和写的操作时，首先并不是对物理数据文件操作，而是先对 buffer_pool 进行操作，再通过 checkpoint&#xA;等机制写回数据文件。该空间的优点是可以提升数据库的性能、加快 SQL 运行速度，缺点是故障恢复速度较慢。&lt;/p&gt;&#xA;&lt;h3&gt;InnoDB Buffer Pool Size 调优&lt;/h3&gt;&#xA;&lt;h4&gt;1. 查看当前 Buffer Pool Size&lt;/h4&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;默认大小为 128M，支持配置的单位时 K、M、G，不支持小数点，如果配置的值不是这些单位，会被转换为字节。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mysql&amp;gt; show variables like &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;%innodb_buffer_pool_size%&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;2. 查看当前 Buffer Pool 使用情况&lt;/h4&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mysql&amp;gt; show engine innodb status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;3. 查看当前 Buffer Pool 命中率&lt;/h4&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mysql&amp;gt; show global status like &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;innodb_buffer_pool_read%&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;MySQL 基准测试&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;修改配置前后需要进行基准测试，以便对比优化效果。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h4&gt;使用 &lt;a href=&#34;https://github.com/akopytov/sysbench&#34;&gt;sysbench&lt;/a&gt; 做基准测试&lt;/h4&gt;&#xA;&lt;h5&gt;1. 安装 sysbench&lt;/h5&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo yum -y install sysbench&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;2. 查看版本&lt;/h5&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysbench --version&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;3. 准备数据&lt;/h5&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysbench oltp_common.lua --time&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;300&lt;/span&gt; --mysql-host&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;10.120.68.91 --mysql-port&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;3306&lt;/span&gt; --mysql-user&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;root --mysql-password&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;xkjc_123 --mysql-db&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;sbtest --table-size&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;1000000&lt;/span&gt; --tables&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt; --threads&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;32&lt;/span&gt; --events&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;999999999&lt;/span&gt; prepare&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;4. 运行测试&lt;/h5&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysbench oltp_read_write.lua --time&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;300&lt;/span&gt; --mysql-host&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;10.120.68.91 --mysql-port&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;3306&lt;/span&gt; --mysql-user&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;root --mysql-password&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;xkjc_123 --mysql-db&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;sbtest --table-size&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;1000000&lt;/span&gt; --tables&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt; --threads&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;16&lt;/span&gt; --events&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;999999999&lt;/span&gt;  --report-interval&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt;  run&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;5. 清理数据&lt;/h5&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysbench oltp_read_write.lua --time&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;300&lt;/span&gt; --mysql-host&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;10.120.68.91 --mysql-port&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;3306&lt;/span&gt; --mysql-user&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;root --mysql-password&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;xkjc_123 --mysql-db&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;sbtest --table-size&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;1000000&lt;/span&gt; --tables&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt; --threads&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;16&lt;/span&gt; --events&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;999999999&lt;/span&gt; --report-interval&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt; cleanup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;6. 效果对比&lt;/h5&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;机器物理内存 16G。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;buffer_pool_size 默认为 128M 时，性能如下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2023/06/06/150923.png&#34; alt=&#34;150923&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;buffer_pool_size 调整为 6G 时，性能如下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2023/06/06/151022.png&#34; alt=&#34;151022&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3&gt;innodb_buffer_pool_size 无法动态调整到 1G 以下问题&lt;/h3&gt;&#xA;&lt;p&gt;如果需要调整 innodb_buffer_pool_size 至 1G 以下，innodb_buffer_pool_instances 参数值必须是 1，否则会报错。&lt;/p&gt;&#xA;&lt;p&gt;如果配置的 innodb_buffer_pool_size 大于 1G，&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_buffer_pool_instances&#34;&gt;innodb_buffer_pool_instances 没有手动配置&#xA;则会自动配置为 8&lt;/a&gt;&#xA;。此时无法把 innodb_buffer_pool_size 动态调整到 1G 以下。&lt;/p&gt;&#xA;&lt;h3&gt;参考&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://cloud.tencent.com/document/product/236/32534&#34;&gt;https://cloud.tencent.com/document/product/236/32534&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://cloud.tencent.com/developer/article/1536046&#34;&gt;https://cloud.tencent.com/developer/article/1536046&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://help.aliyun.com/document_detail/35264.html?spm=a2c4g.53629.0.0.30392049WYKPId&#34;&gt;https://help.aliyun.com/document_detail/35264.html?spm=a2c4g.53629.0.0.30392049WYKPId&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2023/2023-06-06-mysql-innodb-buffer-pool-size/</guid>
    </item>
    <item>
      <title>Java generic &amp; wildcard</title>
      <link>https://blog.yuhaowin.com/2023/2023-03-12-java-generic/</link>
      <description>&lt;h1&gt;Java generic &amp;amp; wildcard&lt;/h1&gt;&#xA;&lt;h3&gt;泛型类&lt;/h3&gt;&#xA;&lt;p&gt;泛型类的定义&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    class name&amp;lt;T1, T2, Tn&amp;gt; { /* ... */ }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Java 把上述 T1, T2, and Tn 称为泛型类型(Generic Types)，或者类型参数(type parameters), 类型参数可以在类中任何地方使用。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class Box&amp;lt;T&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        // T stands for &amp;#34;Type&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private T t;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public void set(T t) { this.t = t; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public T get() { return t; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;泛型类的使用&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Box&amp;lt;Integer&amp;gt; integerBox = new Box&amp;lt;Integer&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Box&amp;lt;String&amp;gt; stringBox = new Box&amp;lt;String&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;泛型在使用时可以是任何的类、接口、数组、甚至是另一个泛型类。如上述的 T, T1, T2, and Tn 可以是 Integer, String, List&lt;String&gt;, List&lt;T&gt; 等等。&lt;/p&gt;&#xA;&lt;h3&gt;泛型接口&lt;/h3&gt;&#xA;&lt;p&gt;和泛型类一样，泛型接口也可以定义一个或多个类型参数，将类型参数置于接口名的后面。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public interface Pair&amp;lt;K, V&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public K getKey();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public V getValue();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class OrderedPair&amp;lt;K, V&amp;gt; implements Pair&amp;lt;K, V&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private K key;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private V value;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public OrderedPair(K key, V value) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;    this.key = key;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;    this.value = value;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public K getKey()&#x9;{ return key; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public V getValue() { return value; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其中 OrderedPair&amp;lt;K, V&amp;gt; 是泛型的定义，implements Pair&amp;lt;K, V&amp;gt; 中的 K 和 V 是泛型的使用，而不是定义，因为OrderedPair&amp;lt;K, V&amp;gt; 已经定义了 K 和 V。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    OrderedPair&amp;lt;String, Box&amp;lt;Integer&amp;gt;&amp;gt; p = new OrderedPair&amp;lt;&amp;gt;(&amp;#34;primes&amp;#34;, new Box&amp;lt;Integer&amp;gt;(...));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;泛型方法&lt;/h3&gt;&#xA;&lt;p&gt;泛型方法有自己声明的类型参数，这些类型参数的声明放在返回值之前。但泛型方法的类型参数的作用域只限于方法本身。适用于静态方法和实例方法以及泛型类的构造器。&#xA;可以被用到方法的参数声明、方法返回值、方法体中变量的声明和类型转换。 泛型方法使得该泛型方法的类型参数独立于类而产生变化。泛型方法和泛型类没有必然关系。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class Util {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public static &amp;lt;K, V&amp;gt; boolean compare(Pair&amp;lt;K, V&amp;gt; p1, Pair&amp;lt;K, V&amp;gt; p2) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            return p1.getKey().equals(p2.getKey()) &amp;amp;&amp;amp;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   p1.getValue().equals(p2.getValue());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Pair&amp;lt;Integer, String&amp;gt; p1 = new Pair&amp;lt;&amp;gt;(1, &amp;#34;apple&amp;#34;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Pair&amp;lt;Integer, String&amp;gt; p2 = new Pair&amp;lt;&amp;gt;(2, &amp;#34;pear&amp;#34;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    boolean same = Util.&amp;lt;Integer, String&amp;gt;compare(p1, p2);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    // 借助类型推断，可以省略类型参数&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    boolean same = Util.compare(p1, p2);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;有界的类型参数&lt;/h3&gt;&#xA;&lt;p&gt;可以限制类型参数的范围，限制上界使用 extends 关键字。这里可以 extends 类和接口。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class NaturalNumber&amp;lt;T extends Integer&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private T n;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public NaturalNumber(T n)  { this.n = n; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public boolean isEven() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            return n.intValue() % 2 == 0;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以在类中使用泛型上界类的方法，如这里 Integer#intValue() 方法。&lt;/p&gt;&#xA;&lt;h3&gt;多个边界的类型参数&lt;/h3&gt;&#xA;&lt;p&gt;类型参数可以有多个上界，用 &amp;amp; 分隔。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;T extends A &amp;amp; B &amp;amp; C&amp;gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这里类型参数 T 拥有 A B C 三个上界，这三个上界可以是类，也可以是接口，如果是类的话，只有有一个类，其他的都是接口，且类必须放在第一个。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Class A { /* ... */ }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    interface B { /* ... */ }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    interface C { /* ... */ }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    class D &amp;lt;T extends A &amp;amp; B &amp;amp; C&amp;gt; { /* ... */ }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;泛型方法中的多个边界&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public static &amp;lt;T extends Comparable &amp;amp; Serializable&amp;gt; T max(T[] a) { ... }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;通配符类型&lt;/h3&gt;&#xA;&lt;p&gt;无边界通配符 Unbounded Wildcards&#xA;通常用于不依赖类型参数的方法中，如下面的 printList 方法。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public static void printList(List&amp;lt;?&amp;gt; list) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for (Object elem: list)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.out.print(elem + &amp;#34; &amp;#34;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System.out.println();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上界通配符 Upper Bounded Wildcards，&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    List&amp;lt;? extends Number&amp;gt; list = new ArrayList&amp;lt;Integer&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public static double sumOfList(List&amp;lt;? extends Number&amp;gt; list) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        double s = 0.0;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for (Number n : list)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            s += n.doubleValue();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        return s;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下界通配符 Lower Bounded Wildcards&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public static void addNumbers(List&amp;lt;? super Integer&amp;gt; list) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for (int i = 1; i &amp;lt;= 10; i++) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            list.add(i);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;类型参数和通配符的区别&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通配符有且仅有一个边界，而类型参数可以有多个边界。&lt;/li&gt;&#xA;&lt;li&gt;通配符可以有一个上界或有一个下界，而类型参数不支持下界。&lt;/li&gt;&#xA;&lt;li&gt;通配符不能在泛型类、泛型接口定义中使用，只能在泛型方法定义中使用。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;类型参数和通配符的选择&lt;/h3&gt;&#xA;&lt;h3&gt;在方法中可以同时使用类型参数和通配符&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public &amp;lt;T&amp;gt; void func(List&amp;lt;? extends T&amp;gt; list, T t) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.add(t); // compile error 不可以修改 list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public &amp;lt;T&amp;gt; void func(List&amp;lt;? super T&amp;gt; list, T t) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.add(t); // 可以修改 list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public &amp;lt;T, E extends T&amp;gt; void func(List&amp;lt;E&amp;gt; list, T t){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.add((E) t); // 可以修改，但是需要强制类型转换&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;通配符中上下界(extents、super) 的选择&lt;/h3&gt;&#xA;&lt;p&gt;遵循 PECS 原则，Producer Extends Consumer Super。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;频繁往外读取内容的，适合用上界Extends，无法往里插入任何元素。&lt;/li&gt;&#xA;&lt;li&gt;经常往里插入的，适合用下界Super，取出来的元素都是 Object 类型。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public static &amp;lt;T&amp;gt; void copy(List&amp;lt;? extends T&amp;gt; src, List&amp;lt;? super T&amp;gt; dest) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        for (int i = 0; i &amp;lt; src.size(); i++)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            dest.set(i, src.get(i));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;参考&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://blog.51cto.com/u_3664660/3213120&#34;&gt;https://blog.51cto.com/u_3664660/3213120&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.oracle.com/javase/tutorial/java/generics/index.html&#34;&gt;https://docs.oracle.com/javase/tutorial/java/generics/index.html&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card&#34;&gt;https://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <pubDate>Sun, 12 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2023/2023-03-12-java-generic/</guid>
    </item>
    <item>
      <title>Spring Bean 被提前创建，导致 BeanPostProcessor 对其失效</title>
      <link>https://blog.yuhaowin.com/2023/2023-03-04-spring-bean-post-processor/</link>
      <description>&lt;h1&gt;Spring Bean 被提前创建，导致 BeanPostProcessor 对其失效&lt;/h1&gt;&#xA;&lt;h2&gt;问题&lt;/h2&gt;&#xA;&lt;p&gt;在一个 Spring Boot 项目中，我们集成了 Shiro 权限框架，在我们实现 AuthorizingRealm 的 UserRealm 类中，通过 &lt;code&gt;@Autowired&lt;/code&gt; 注解注入了一个 LoginService 类，用于获取用户信息。&lt;/p&gt;&#xA;&lt;p&gt;LoginService 中有使用自定义注解用于在 Bean 实例化阶段获取配置信息。通过 BeanPostProcessor 实现的。但 LoginService 在实例化的使用，没有被 BeanPostProcessor 增强。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Configuration&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class ShiroConfiguration {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Bean&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        public UserRealm userRealm() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            UserRealm userRealm = new UserRealm();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            return userRealm;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Slf4j&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class UserRealm extends AuthorizingRealm {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Autowired&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private LoginService loginService;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ｝    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class LoginServiceImpl implements LoginService {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Config(&amp;#34;prefix&amp;#34;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private String prefix;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;原因&lt;/h2&gt;&#xA;&lt;p&gt;UserRealm 是通过 &lt;code&gt;@Configuration&lt;/code&gt; + &lt;code&gt;@Bean&lt;/code&gt; 的方式注入到 Spring 容器中的。通过这种方式创建的 UserRealm 实例时，会导致 UserRealm 依赖的 LoginService 实例被提前创建，从而导致 BeanPostProcessor 对其失效。&lt;/p&gt;&#xA;&lt;h2&gt;解决&lt;/h2&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;@Lazy&lt;/code&gt; 注解，延迟 LoginService 实例的创建。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Slf4j&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    public class UserRealm extends AuthorizingRealm {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Lazy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        @Autowired&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        private LoginService loginService;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ｝    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&#34;https://www.jianshu.com/p/916a7d8311bf&#34;&gt;参考&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Sat, 04 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2023/2023-03-04-spring-bean-post-processor/</guid>
    </item>
    <item>
      <title>在 mac 下构建自己的输入法</title>
      <link>https://blog.yuhaowin.com/2022/2022-12-25-mac-yourself-input-method/</link>
      <description>&lt;h1&gt;在 mac 下构建自己的输入法&lt;/h1&gt;&#xA;&lt;p&gt;mac 是支持构建自己的输入法的，核心是编写一个 .inputplugin 的文件。&lt;/p&gt;&#xA;&lt;p&gt;要求这个文件是 UTF-16 的编码格式。文件的具体格式见&lt;a href=&#34;https://support.apple.com/zh-cn/guide/mac-help/mchlp2866/13.0/mac/13.0&#34;&gt;官网示例&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;我这里编写的是一个输入英语音标的输入法：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# https://support.apple.com/zh-cn/guide/mac-help/mchlp2866/mac&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# D.J. 音标 - (IPA88)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;METHOD: TABLE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ENCODE: SC&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PROMPT: D.J. 音标&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DELIMITER: ,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION: 1.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MAXINPUTCODE: &lt;span style=&#34;color:#099&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VALIDINPUTKEY: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TERMINPUTKEY: &lt;span style=&#34;color:#099&#34;&gt;123456789&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BEGINCHARACTER&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 测试内容&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mac     💻&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apple &#x9;🍎&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 短元音&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a &#x9;æ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;e &#x9;e,ə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;i &#x9;i,ɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;o &#x9;ɒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;u &#x9;u,ʌ,ʊ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 长元音&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a;&#x9;ɑː&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;e; &#x9;ɜː&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;i; &#x9;iː&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;o; &#x9;ɔː&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;u; &#x9;uː&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 双元音&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;au &#x9;aʊ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ai &#x9;aɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ei &#x9;eɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;eu &#x9;əʊ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ee &#x9;eə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ie &#x9;ɪə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;oi &#x9;ɔɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ue &#x9;ʊə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 辅音，英音和美音没有区别，D.J.63、D.J.88 和 K.K. 音标一致&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;p &#x9;p&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b &#x9;b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;t &#x9;t&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d &#x9;d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;k &#x9;k&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;g &#x9;g&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m &#x9;m&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n &#x9;n,ŋ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;f &#x9;f&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v &#x9;v&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s &#x9;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;z &#x9;z&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;th &#x9;θ,ð&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x &#x9;ʃ,ʒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tx &#x9;tʃ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dx &#x9;dʒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;h &#x9;h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;w &#x9;w&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;r &#x9;r&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;j &#x9;j&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;l &#x9;l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 辅音连缀，可以不认为是新的音标&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ts &#x9;ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dz &#x9;dz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tr &#x9;tr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dr &#x9;dr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 常见两音标组合 - 待完善&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;an &#x9;ʌn,æn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;am &#x9;ʌm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ek &#x9;ək&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;di &#x9;dɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;en &#x9;ən&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;em &#x9;əm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;er &#x9;ər&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;eu &#x9;əu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fe &#x9;fə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ga &#x9;gæ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hi &#x9;hɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ke &#x9;kə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ik &#x9;ɪk&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;in &#x9;ɪn,ɪŋ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ir &#x9;ɪr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kj &#x9;kjʊ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;la &#x9;lʌ,læ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;le &#x9;lə,lɛ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;li &#x9;lɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;me &#x9;mə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mo &#x9;mɒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ne &#x9;nə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ni &#x9;nɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ou &#x9;oʊ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pa &#x9;pæ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ra &#x9;ræ,rʌ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;re &#x9;rə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ri &#x9;rɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sa &#x9;sʌ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;se &#x9;sə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;si &#x9;sɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;so &#x9;sɒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ta &#x9;tæ,tʌ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;te &#x9;tə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ti &#x9;tɪ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;to &#x9;tɒ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ue &#x9;uə&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ve &#x9;və&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xn &#x9;ʃn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xl &#x9;ʃl&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;####### 符号&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/ &#x9;/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;, &#x9;ʼ,ʻ,ː,ʽ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;. &#x9;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ENDCHARACTER&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;编写完成后保存，双击改文件就会安装到内建的输入法中，该文件会保存在 &lt;code&gt;~/Library/Input Methods&lt;/code&gt; 目录下。如果不需要可以直接删除。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2022/12/25/032015.png&#34; alt=&#34;032015&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;安装或删除自定义的输入法后，可能需要重新登录系统，或重启系统。&lt;/p&gt;&#xA;&lt;p&gt;效果如下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2022/12/25/031855.png&#34; alt=&#34;031855&#34; /&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Sun, 25 Dec 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2022/2022-12-25-mac-yourself-input-method/</guid>
    </item>
    <item>
      <title>到底如何设置线程池的核心线程数、最大线程数</title>
      <link>https://blog.yuhaowin.com/2022/2022-04-27-how-to-set-thread-nums/</link>
      <description>&lt;h1&gt;到底如何设置线程池的核心线程数、最大线程数&lt;/h1&gt;&#xA;&lt;h4&gt;线程池在业务中的实践&lt;/h4&gt;&#xA;&lt;h5&gt;场景一：快速响应用户请求&lt;/h5&gt;&#xA;&lt;p&gt;这种场景可以将用户请求封装成任务并发执行，缩短总体响应时间，该场景需要获取最大的响应速度满足客户，应该不应该设置缓冲队列，缓冲并发任务。可以适当调高 corePoolSize 和 maxPoolSize 去尽可能创造多的线程快速执行任务。&lt;/p&gt;&#xA;&lt;h5&gt;场景2：快速处理批量任务&lt;/h5&gt;&#xA;&lt;p&gt;这种场景一般是需要大量执行离线任务，是吞吐量优先，但是不是要求瞬时完成，也就是要求尽可能在单位时间内处理更多的任务，可以使用缓冲队列，缓冲任务，corePoolSize 不适合特别大，太大频繁上下文切换，反而影响吞吐量。&lt;/p&gt;&#xA;&lt;h4&gt;业界的线程数配置方案一般都是比较理想化&lt;/h4&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;并发任务的执行情况和任务类型相关，IO密集型和CPU密集型的任务运行起来的情况差异非常大，较难合理预估，这导致很难有一个简单有效的通用公式帮我们直接计算出结果。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;CPU 密集型任务&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;比如像加解密，压缩、计算等一系列需要大量耗费 CPU 资源的任务，大部分场景下都是纯 CPU 计算。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;核心线程数，可以设置为CPU核数 + 1 , +1是为了实现最优的利用率。即使当密集型的线程由于偶尔的内存页失效或其他原因导致阻塞时，这个额外的线程也能确保 CPU 的时钟周期不会被浪费，从而保证 CPU 的利用率。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;IO 密集型任务&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;比如像 MySQL 数据库、文件的读写、网络通信等任务，这类任务不会特别消耗 CPU 资源，但是 IO 操作比较耗时，会占用比较多时间。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;核心数设置的一般比较多一些，因为 IO 读写速度相比于 CPU 的速度而言是比较慢的，核心线程数=CPU 核心数 * (1 + IO 耗时/ CPU 耗时)&lt;/p&gt;&#xA;&lt;p&gt;尽管通过严谨的评估，依然很难一次计算出合适的参数，因此，可以换一个思路，把修改参数的成本降低，这样可以在告警发生时，快速调整，尽快恢复。&lt;/p&gt;&#xA;&lt;h4&gt;动态调整线程池参数&lt;/h4&gt;&#xA;&lt;p&gt;简化参数配置，关注核心参数，corePoolSize maxPoolSize workQueue，&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;延时优先的场景，同步队列。&lt;/li&gt;&#xA;&lt;li&gt;吞吐量优先的场景，使用有界队列。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;修改 corePoolSize&#xA;ThreadPoolExecutor#setCorePoolSize：在运行期间可以通过该方法修改 corePoolSize，会直接覆盖之前的 corePoolSize 值。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当前值小于之前值，表示有多余的 work 线程，此时会向当前 idle 的 worker 线程发起中断请求以实现回收，其余多余的 worker 在下次 idel 的时候也会被回收。&lt;/li&gt;&#xA;&lt;li&gt;当前值大于之前值，并且队列里有任务的时候，会创建新的线程执行任务。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;修改 maxPoolSize&#xA;ThreadPoolExecutor#setMaximumPoolSize&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当前值小于之前值，超过的，并且已经在运行的线程会在 idle 的时候停止。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;修改 workQueueSize&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;LinkedBlockingQueue 没有开放修改 capacity 的方法，可以参考 LinkedBlockingQueue 自定义支持修改 capacity 的 Queue。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;DynamicThreadPool&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ThreadPoolExecutor threadPoolExecutor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[]&lt;/span&gt; args&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throws&lt;/span&gt; InterruptedException &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        DynamicThreadPool threadPool &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; DynamicThreadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;buildThreadPool&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;threadPoolExecutor&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;init&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; 0&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; i &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; 15&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; i&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;++)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; finalI &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; i&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;threadPoolExecutor&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;submit&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;threadPoolExecutor&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;创建任务: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;+&lt;/span&gt; finalI&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    TimeUnit&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;SECONDS&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;sleep&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;10&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;InterruptedException e&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; RuntimeException&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;e&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;});&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;modifyMaxSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;10&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;modifyCoreSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;10&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TimeUnit&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;SECONDS&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;sleep&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;2&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPool&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;modifyWorkQueueSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;100&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; ThreadPoolExecutor &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;buildThreadPool&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ThreadPoolExecutor executor &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ThreadPoolExecutor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                2&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                5&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                30&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                TimeUnit&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;MILLISECONDS&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;new&lt;/span&gt; ResizeLinkedBlockingQueue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;10&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;threadPoolExecutor&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;return&lt;/span&gt; executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;modifyCoreSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; num&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPoolExecutor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;setCorePoolSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;num&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;modifyMaxSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; num&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        threadPoolExecutor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;setMaximumPoolSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;num&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;modifyWorkQueueSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;int&lt;/span&gt; size&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ResizeLinkedBlockingQueue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Runnable&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; queue &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;ResizeLinkedBlockingQueue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Runnable&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;)&lt;/span&gt; threadPoolExecutor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getQueue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        queue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;setCapacity&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;size&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;ThreadPoolExecutor executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; String name&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ResizeLinkedBlockingQueue queue &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;ResizeLinkedBlockingQueue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getQueue&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        String message &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt; String&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;%s 核心线程数: %s,最大线程数: %s,活动线程数: %s,完成任务数: %s,队列大小: %s,队列剩余: %s&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                name&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getCorePoolSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getMaximumPoolSize&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getActiveCount&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                executor&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;getCompletedTaskCount&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                queue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;size&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                queue&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;remainingCapacity&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;());&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        System&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;message&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;问题一：线程池被创建后里面有线程吗？如果没有的话，你知道有什么方法对线程池进行预热吗？&lt;/p&gt;&#xA;&lt;p&gt;默认情况线程池被创建后如果没有任务过来，里面是不会有线程的。如果需要预热的话可以调用下面的两个方法：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;prestartCoreThread 启动一个核心线程&lt;/li&gt;&#xA;&lt;li&gt;prestartAllCoreThreads 启动所有的核心线程&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;问题二：核心线程数会被回收吗？需要什么设置？&lt;/p&gt;&#xA;&lt;p&gt;核心线程数默认是不会被回收的，如果需要回收核心线程数，需要调用下面的方法：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;allowCoreThreadTimeOut(boolean value)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;reference：&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html&#34;&gt;美团&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://mp.weixin.qq.com/s/YbyC3qQfUm4B_QQ03GFiNw&#34;&gt;公众号&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Wed, 27 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2022/2022-04-27-how-to-set-thread-nums/</guid>
    </item>
    <item>
      <title>VIDEO-03｜boku-ga</title>
      <link>https://blog.yuhaowin.com/videos/2022/2022-04-15-video-03/</link>
      <description>&lt;h1&gt;VIDEO-03｜boku-ga&lt;/h1&gt;&#xA;&lt;video id=&#34;video&#34; controls=&#34;controls&#34; preload=&#34;none&#34; poster1=&#34;https://image.yuhaowin.com/2020/04/14/134142.jpg&#34; style=&#34;width: 100%; height: 100%;&#34;&gt;&#xA;&lt;source id=&#34;mp4&#34; src=&#34;https://image.yuhaowin.com/v/boku-ga.mp4&#34; type=&#34;video/mp4&#34;&gt;&#xA;&lt;/video&gt;&#xA;</description>
      <pubDate>Fri, 15 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/videos/2022/2022-04-15-video-03/</guid>
    </item>
    <item>
      <title>为什么要有 StringTable</title>
      <link>https://blog.yuhaowin.com/2022/2022-03-24-string-table/</link>
      <description>&lt;h1&gt;为什么要有 StringTable&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In computer science, &lt;a href=&#34;https://en.wikipedia.org/wiki/String_interning&#34;&gt;string interning&lt;/a&gt; is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;为什么字符串要被设计为 Immutable？&lt;/p&gt;&#xA;&lt;p&gt;1、便于实现 StringTable。&lt;/p&gt;&#xA;&lt;p&gt;2、在多线程环境下，并发读取同一个字符串是安全的，不会产生竞争。&lt;/p&gt;&#xA;&lt;p&gt;3、加快字符串处理速度，字符串不可变，hashcode 唯一，可以在对象中缓存 hashcode。&lt;/p&gt;&#xA;</description>
      <pubDate>Thu, 24 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2022/2022-03-24-string-table/</guid>
    </item>
    <item>
      <title>计算机相关常见概念</title>
      <link>https://blog.yuhaowin.com/2022/2022-03-23-common-concept/</link>
      <description>&lt;h2&gt;计算机相关常见概念&lt;/h2&gt;&#xA;&lt;h3&gt;TP:分位值(top percentile)&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The TP9999 is a minimum time under which 99.99% of requests have been served.&lt;/p&gt;&#xA;&lt;p&gt;可以认为 TP9999 的意思是保证 99.99% 请求都能被响应需要的最小耗时。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h4&gt;计算方法&lt;/h4&gt;&#xA;&lt;p&gt;calculating TP is very simple:&#xA;1.sort all respond times in ascending order，eg: [2s, 10s, 100s, 1000s]&#xA;2.find latest item in portion you need to calculate.&#xA;2.1 for TP50 it will be ceil &lt;code&gt;4*0.5=2&lt;/code&gt; requests. You need 2nd request.&#xA;2.2 for TP90 it will be ceil &lt;code&gt;4*0.9=4&lt;/code&gt; You need 4th request.&#xA;3.we get time for the item found above. TP50=10s. TP90=1000s&lt;/p&gt;&#xA;&lt;p&gt;+++++++++&lt;/p&gt;&#xA;&lt;h3&gt;SLA:服务等级协议(service level agreement)&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;服务提供商与用户间定义的一种双方认可的协定，用来保障服务的性能和可用性。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h4&gt;计算方法&lt;/h4&gt;&#xA;&lt;p&gt;1年 = 365天 = 8760小时,可以计算全年可停机的时间。&lt;/p&gt;&#xA;&lt;p&gt;SLA99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小时&lt;/p&gt;&#xA;&lt;p&gt;SLA99.99 = 8760 * 0.0001 = 0.876小时 = 0.876 * 60 = 52.6分钟&lt;/p&gt;&#xA;&lt;p&gt;SLA99.999 = 8760 * 0.00001 = 0.0876小时 = 0.0876 * 60 = 5.26分钟&lt;/p&gt;&#xA;&lt;h3&gt;Amdahl‘s law 阿姆达尔定律&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;是并行计算领略一个非常著名的定律,描述对于一个固定计算任务，在并行处理下的加速比。&lt;/p&gt;&#xA;&lt;p&gt;S=1/((1-f)+f/p)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;假设一个大的任务串行处理耗时 1 个单位时间，其中有 f 部分可以进行并行化处理，现在的耗时为，(1-f)+f/p&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2022/04/27/115234.png&#34; alt=&#34;115234&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;reference: &lt;a href=&#34;https://www.youtube.com/watch?v=Axx2xuB-Xuo&#34;&gt;Youtube-Amdahl&#39;s Law&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Wed, 23 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2022/2022-03-23-common-concept/</guid>
    </item>
    <item>
      <title>英语发音技巧</title>
      <link>https://blog.yuhaowin.com/2022/2022-01-26-english-skill/</link>
      <description>&lt;h1&gt;英语发音技巧&lt;/h1&gt;&#xA;&lt;h2&gt;英语的连读现象&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;英语和中文的一个很大区别是英语在句中有大量的连读现象，连读是造成听力不好和口语不地道的原因之一，连读有连音、加音、同化、异化等多种现象。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h3&gt;一、连音 - Catenation / Liaison&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;单词(辅音结尾) + 单词(元音开头)&lt;/strong&gt; ，连音并不是无中生有凭空捏造一个音插入句子中。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;上一个单词以辅音结尾下一个单词以元音开头时，上一个词词尾的音和下一个词开头的音会连在一起，连音造成的困扰是，很难区分单词的界限，尤其是我们中国人喜欢把句子断句为一个个以 &lt;code&gt;辅音开头 + 元音结尾&lt;/code&gt; 的词，因为大多数的中文都是如此。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;因此发音时需要注意一下几点：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;在说英文的时候不要按中文习惯划分单词的界限&lt;/li&gt;&#xA;&lt;li&gt;以辅音结尾的单词，其结尾的辅音要发到位，并且不要加上不存在的元音&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;例子：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;not at all --- not 词尾连上 at 开头，at 词尾连上 all 开头&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;take it easy -- take 和 it 后不加不存在的元音&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;in an instant -- in 和 an 结尾的鼻音发到位&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;all of it -- all 和 of 连音&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;couple of weeks off -- couple 和 of 连音&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;all over -- all over 连音&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;二、加音 - Intrusion&lt;/h3&gt;&#xA;&lt;p&gt;在英语中，元音 + 元音，因为界限不明确，很容易糊在一起，很难发音，因此需要人工干预。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;把 a -&amp;gt; an，例如 a apple 都是元音开头，把 a -&amp;gt; an 后，an 和 apple 可以连音&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;单词(元音结尾) + 单词(元音开头)，会加上一个之前不存在的音，使得发音连贯，这个不存在的音，是一个很微弱的过度音。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;加音的情况有：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;前一个单词以元音 /uː/、/ʊ/、/əʊ/、/aʊ/ 结尾的单词 + 单词(元音开头)时，会加一个 /w/ 过渡。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;just do it -- do 和 it 会加一个 /w/&lt;/li&gt;&#xA;&lt;li&gt;who is&lt;/li&gt;&#xA;&lt;li&gt;too often&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;前一个单词以元音 /iː/、/ɪ/、/eɪ/、/aɪ/、/ɔɪ/ 结尾的单词 + 单词(元音开头)时，会加一个 /j/ 过渡。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I am&lt;/li&gt;&#xA;&lt;li&gt;she asked&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;前一个单词以元音 /ə/、/ɑː/、/ɔː/ 结尾的单词 + 单词(元音开头)时，会加一个 /r/ 过渡 - （英式）。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the idea of -- idea 和 of 会加一个 /r/&lt;/li&gt;&#xA;&lt;li&gt;law and order -- law 和 and&lt;/li&gt;&#xA;&lt;li&gt;china and india -- china 和 and&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;前一个单词以 r 结尾 + 单词(元音开头)时，会加一个 /r/ 过渡 - （英式）。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;bear it&lt;/li&gt;&#xA;&lt;li&gt;gear up&lt;/li&gt;&#xA;&lt;li&gt;far away&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3&gt;三、同化 - Assimilation&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;一前一后的两个音碰到一起时，互相影响改变了原来的音。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h4&gt;逆行同化 - regressive assimilation&lt;/h4&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;前一个音受后一个音影响，前一个音改变，后一个音不变。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;1、无声除阻 - unreleased stop (塞音(爆破音) - /k/、/t/、/d/ + 辅音),在发塞音的时候气流释放不完全，也被称为不完全爆破，失去爆破、失爆&lt;/p&gt;&#xA;&lt;p&gt;如 look back、that job、good night 遇到辅音后，前面的 k t d 变弱了很多，而不是完全发出来。&lt;/p&gt;&#xA;&lt;p&gt;2、浊音变清音 - devoicing&lt;/p&gt;&#xA;&lt;p&gt;声带震动的浊音变成声带不振振动的清音&lt;/p&gt;&#xA;&lt;p&gt;have to -&amp;gt;  have 中的 /v/ 变为 /f/，因为前一个浊音 + 后一个清音，声带要突然停止，不好发音，因此前一个浊音也改为清音&lt;/p&gt;&#xA;&lt;p&gt;of course -&amp;gt; of 中的 /v/ 变为 /f/&lt;/p&gt;&#xA;&lt;p&gt;3、鼻化 - nasalization&lt;/p&gt;&#xA;&lt;p&gt;前面一个音是鼻音时，也有可能受到后一个音的影响&lt;/p&gt;&#xA;&lt;p&gt;in person -&amp;gt; /n/ 本来发音的时候不需要闭住上下嘴唇，但是受到后面的 /p/ 这个需要闭住嘴唇的音的影响，所以 /n/ -&amp;gt; /m/&lt;/p&gt;&#xA;&lt;p&gt;impolite 、impatient，这里表示反义的词把 n -&amp;gt; m&lt;/p&gt;&#xA;&lt;h4&gt;顺行同化 - progressive assimilation&lt;/h4&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;后一个音受前面的音影响。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;主要是单词复数结尾的 s，例如：&lt;/p&gt;&#xA;&lt;p&gt;books /bʊks/ 复数结尾读 /s/，/k/ 是声带不振动的清音，后面就发清音 /s/ 更容易，更轻松&lt;/p&gt;&#xA;&lt;p&gt;dogs /dɒɡz/ 复数结尾读 /z/，/g/ 是声带振动的浊音，后面就发浊音 /z/&lt;/p&gt;&#xA;&lt;h4&gt;前后相互影响&lt;/h4&gt;&#xA;&lt;p&gt;1、融合 - coalescence&lt;/p&gt;&#xA;&lt;p&gt;后一个音是半元音 /j/ 的时候&lt;/p&gt;&#xA;&lt;p&gt;/s/ + /j/ = /ʃ/&lt;/p&gt;&#xA;&lt;p&gt;God bless you&lt;/p&gt;&#xA;&lt;p&gt;/z/ + /j/ = /ʒ/&lt;/p&gt;&#xA;&lt;p&gt;as you wish&lt;/p&gt;&#xA;&lt;p&gt;/t/ + /j/ = /tʃ/&lt;/p&gt;&#xA;&lt;p&gt;Nice to meet you&lt;/p&gt;&#xA;&lt;p&gt;/d/ + /j/ = /dʒ/&lt;/p&gt;&#xA;&lt;p&gt;Did you do it？&lt;/p&gt;&#xA;&lt;p&gt;2、辅音延长 - gemination&lt;/p&gt;&#xA;&lt;p&gt;前一个音和后一音是同一个音，两个音会自然合并起来，只需要发一次&lt;/p&gt;&#xA;&lt;p&gt;life force&lt;/p&gt;&#xA;&lt;p&gt;fish shop&lt;/p&gt;&#xA;&lt;p&gt;black coffee&lt;/p&gt;&#xA;&lt;h3&gt;四、异化 -Dissimilation&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;主要发生在字母 s 和 r 上。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;1、/s/ 后面的 /t/、/k/、/p/ 会变成不送气的版本，声带是不振动的，严格说不同于 /d/、/g/、/b/，它们是声带振动的。&lt;/p&gt;&#xA;&lt;p&gt;2、字母 r，在美式英语中会让之前的元音 r化(r-coloring)&lt;/p&gt;&#xA;&lt;h3&gt;五、省音(吞音) - Elision&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;主要指有些本来该发的音没有发。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;1、英语单词中的省音&lt;/p&gt;&#xA;&lt;p&gt;diff&lt;strong&gt;e&lt;/strong&gt;rent 中 f 后面的 e 没有发音&lt;/p&gt;&#xA;&lt;p&gt;int&lt;strong&gt;e&lt;/strong&gt;resting 中 t 后面的 e 没有发音&lt;/p&gt;&#xA;&lt;p&gt;fam&lt;strong&gt;i&lt;/strong&gt;ly 中的 i 的音可以选择读，也可以选择不读&lt;/p&gt;&#xA;&lt;p&gt;有些词中的音是一定要省略的，这是历史省音，下列加粗字母不发音&lt;/p&gt;&#xA;&lt;p&gt;de&lt;strong&gt;b&lt;/strong&gt;t、su&lt;strong&gt;b&lt;/strong&gt;tle、&lt;strong&gt;k&lt;/strong&gt;now、&lt;strong&gt;k&lt;/strong&gt;nee、&lt;strong&gt;w&lt;/strong&gt;rite、&lt;strong&gt;w&lt;/strong&gt;rong、&lt;strong&gt;w&lt;/strong&gt;rapper、chris&lt;strong&gt;t&lt;/strong&gt;mas、san&lt;strong&gt;d&lt;/strong&gt;wich、han&lt;strong&gt;d&lt;/strong&gt;bag、hist&lt;strong&gt;o&lt;/strong&gt;&#xA;ry、fact&lt;strong&gt;o&lt;/strong&gt;ry、math&lt;strong&gt;e&lt;/strong&gt;matics&lt;/p&gt;&#xA;&lt;p&gt;2、单词和单词之间的省音&lt;/p&gt;&#xA;&lt;p&gt;/t/、/d/ 这两个音经常在句中被省音，&lt;/p&gt;&#xA;&lt;p&gt;las&lt;strong&gt;t&lt;/strong&gt; year 可以把 t 省略，t 可以无声除阻&lt;/p&gt;&#xA;&lt;p&gt;you an&lt;strong&gt;d&lt;/strong&gt; me&lt;/p&gt;&#xA;&lt;p&gt;还有 h /h/ 和 g /ŋ/ 也经常被省音&lt;/p&gt;&#xA;&lt;p&gt;H-dropping&lt;/p&gt;&#xA;&lt;p&gt;get &lt;strong&gt;h&lt;/strong&gt;im、tell &lt;strong&gt;h&lt;/strong&gt;er&lt;/p&gt;&#xA;&lt;p&gt;G-dropping 经常出现在 ing 结尾中&lt;/p&gt;&#xA;&lt;p&gt;Are you listening 省略了结尾的 /ŋ/&lt;/p&gt;&#xA;&lt;p&gt;更多例子：&lt;/p&gt;&#xA;&lt;p&gt;next door、most common、must be、give me that、what‘s his name？&lt;/p&gt;&#xA;&lt;h3&gt;六、弱读 - Reduction / Weak forms&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;指的是一些词在词组、语句中元音发生了变化，变为另外的元音。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;默认发音&lt;/p&gt;&#xA;&lt;p&gt;to /tuː/ --&amp;gt;    go to school /tə/&lt;/p&gt;&#xA;&lt;p&gt;at /æt/ --&amp;gt;     look at me /ət/&lt;/p&gt;&#xA;&lt;p&gt;but /bʌt/ --&amp;gt;     sad but true /bət/&lt;/p&gt;&#xA;&lt;p&gt;can /kæn/ --&amp;gt;     I can do it /kən/&lt;/p&gt;&#xA;&lt;p&gt;这些词弱读是为了发音方便，说话更自然。&lt;/p&gt;&#xA;&lt;p&gt;一般常用的、少音节的虚词如：介词、代词、连词都会有弱读，它们不影响意思的主要意思，弱读时中间的元音一般都会变成中央元音，如下列这里：&lt;/p&gt;&#xA;&lt;p&gt;介词：at、for、from、of、to&lt;/p&gt;&#xA;&lt;p&gt;连词：and、but&lt;/p&gt;&#xA;&lt;p&gt;冠词：an、some&lt;/p&gt;&#xA;&lt;p&gt;代词：you、us、them、her&lt;/p&gt;&#xA;&lt;p&gt;助动词：am、are、have、has、do、does、would、can、could、should&lt;/p&gt;&#xA;&lt;p&gt;还有一些弱读的元音 /iː/ -&amp;gt; /ɪ/, 如：he、she、me&lt;/p&gt;&#xA;&lt;h3&gt;七、缩读 - Contraction&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;主要是指两个词合并为一个词，也就是缩写导致的音节变少。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;want to = wanna&lt;/p&gt;&#xA;&lt;p&gt;go to = gonna&lt;/p&gt;&#xA;&lt;p&gt;have got to = gotta&lt;/p&gt;&#xA;&lt;p&gt;out of = outta&lt;/p&gt;&#xA;&lt;p&gt;kind of = kinda&lt;/p&gt;&#xA;&lt;p&gt;a lot of = a lotta&lt;/p&gt;&#xA;&lt;p&gt;don&#39;t know = dunno&lt;/p&gt;&#xA;&lt;p&gt;give me = gimme&lt;/p&gt;&#xA;&lt;p&gt;would have = would&#39;ve / would&#39;a&lt;/p&gt;&#xA;&lt;p&gt;you and I = you &#39;n&#39; I&lt;/p&gt;&#xA;&lt;p&gt;come on = c&#39;mon&lt;/p&gt;&#xA;&lt;p&gt;what are you = wachya / watcha&lt;/p&gt;&#xA;&lt;p&gt;what do you = whaddya / wadya&lt;/p&gt;&#xA;&lt;p&gt;what did you = whatdja / wadja&lt;/p&gt;&#xA;&lt;p&gt;can not = can&#39;t&lt;/p&gt;&#xA;&lt;p&gt;good bye = g&#39;bye&lt;/p&gt;&#xA;&lt;hr /&gt;&#xA;&lt;h3&gt;爆破音 / 塞音 - Plosive / stop&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;发音器官先阻挡气流再释放气流而发出的音，英语中的爆破音有：/p/、/b/、/t/、/d/、/k/、/g/，喉塞音也可以归为塞音&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;发塞音有三个阶段：&lt;/p&gt;&#xA;&lt;p&gt;1、第一阶段：成阻 - 发音部位紧闭&lt;/p&gt;&#xA;&lt;p&gt;2、第二阶段：持阻 - 让气流聚集，形成压力&lt;/p&gt;&#xA;&lt;p&gt;3、第三阶段：除阻 - 除去气流的阻碍&lt;/p&gt;&#xA;&lt;p&gt;当一个塞音后面紧跟另一个塞音时，第一个塞音的除阻阶段后，马上紧跟第二个塞音的成阻阶段，在快速的语流中有点不方便，因此，第一个音的除阻阶段不真正的释放气流，而只做一个动作，这种现象就是无声除阻、不完全爆破、失去爆破、失爆。&lt;/p&gt;&#xA;&lt;p&gt;塞音后面跟辅音时需要无声除阻&lt;/p&gt;&#xA;&lt;p&gt;单词内：doc&lt;strong&gt;t&lt;/strong&gt;or、frien&lt;strong&gt;d&lt;/strong&gt;ly、depar&lt;strong&gt;t&lt;/strong&gt;ment、be&lt;strong&gt;d&lt;/strong&gt;time、mi&lt;strong&gt;d&lt;/strong&gt;night、la&lt;strong&gt;te&lt;/strong&gt;ly&lt;/p&gt;&#xA;&lt;p&gt;短语：hot dog、not good、bad day、big girl、good job、fried chicken、bad name&lt;/p&gt;&#xA;</description>
      <pubDate>Wed, 26 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2022/2022-01-26-english-skill/</guid>
    </item>
    <item>
      <title>java -jar some.jar</title>
      <link>https://blog.yuhaowin.com/2021/2021-12-25-java-jar/</link>
      <description>&lt;h1&gt;java -jar some.jar&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;执行 java -jar some.jar 后发生了什么？&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;一般而已，一个 jar 包，其实的本质就一个 zip 包，是一堆 class 文件的集合，class 文件按照它们的包名分布在各个文件夹中的。&lt;/p&gt;&#xA;&lt;p&gt;JVM 被设计成只有一个使命：按照类的全限定名字，加载、执行类。&lt;/p&gt;&#xA;&lt;p&gt;全限定名 - Fully Qualified Name 就是包含了包名的类的名字，例如：&lt;code&gt;com.company.Application&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;这样 JVM 就可以根据全限定名顺藤摸瓜找到类的 class 文件，然后加载执行。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;JVM 是如何找到 class 文件的呢？&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;是通过 -classpath 的参数指定了 class 文件所在的目录&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2021/12/25/230248.png&#34; alt=&#34;230248&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;通过 -classpath 设置的不是一个目录，而是一串目录，jar 包也可以看成是一个目录，目录和目录之间使用冒号 &lt;code&gt;:&lt;/code&gt; 分隔&lt;/p&gt;&#xA;&lt;p&gt;JVM 和 JVM 的包管理机制非常简单：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;JVM 一辈子只干一件事，读字节码，执行字节码；&lt;/li&gt;&#xA;&lt;li&gt;每当JVM看到一个全限定名称，就尝试从 classpath 中加载。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;我们需要做的，就是把 JVM 所需要的字节码完整、正确的给到 classpath。&lt;/p&gt;&#xA;&lt;p&gt;完整 - 意思是任何时候 JVM 都不会抱怨找不到某个类（NoClassDefFoundError）&lt;/p&gt;&#xA;&lt;p&gt;正确 - 意思是给到 classpath 的字节码的版本是正确的（NoSuchMethodError）&lt;/p&gt;&#xA;&lt;p&gt;当执行完 java -jar some.jar 后，会发生什么呢？&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Java.c中的LoadMainClass方法负责加载 jar 包中 main 方法所在的类，该方法首先加载 sun.launcher.LauncherHelper 类。&lt;/li&gt;&#xA;&lt;li&gt;调用 LauncherHelper 类中的checkAndLoadMain方法&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.yuhaowin.com/2021/12/26/000653.png&#34; alt=&#34;000653&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;jdk 自带的 AppClassLoader 只能加载只包含 class 文件的 jar，那 jar in jar 如果加载呢，就需要自定义 classloader 了&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://zhuanlan.zhihu.com/p/57834746&#34;&gt;Java包管理的那些事1&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://zhuanlan.zhihu.com/p/57869026&#34;&gt;Java包管理的那些事2&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;Java%E5%8C%85%E7%AE%A1%E7%90%86%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B3&#34;&gt;Java包管理的那些事3&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://zhuanlan.zhihu.com/p/65388744&#34;&gt;Java包管理的那些事4&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://blog.csdn.net/ROger__wonG/article/details/39900717&#34;&gt;执行Java -jar somefile.jar时发生了什么一&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://blog.csdn.net/ROger__wonG/article/details/39972585&#34;&gt;执行Java -jar somefile.jar时发生了什么二&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <pubDate>Sat, 25 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.yuhaowin.com/2021/2021-12-25-java-jar/</guid>
    </item>
  </channel>
</rss>