news 2026/9/26 6:11:08

SAP ABAP 多线程,还在用老掉牙的 NEW TASK RFC?看完你会删掉那堆 WAIT UNTIL

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SAP ABAP 多线程,还在用老掉牙的 NEW TASK RFC?看完你会删掉那堆 WAIT UNTIL

SAP ABAP 多线程,还在用老掉牙的 NEW TASK RFC?看完你会删掉那堆 WAIT UNTIL

副标题:第一次学并行,先让 10 个快递同时盖章,再套到批量 BAPI。
读者:会写内表、LOOP、CALL FUNCTION,还在用CALL FUNCTION ... STARTING NEW TASK自己数任务、自己WAIT UNTIL。
读完你能:丢掉那堆 RFC 样板,用CL_ABAP_PARALLEL拆包并行,并看懂物料扩展程序ZMMU002S为什么那样写。
建议先只看第 1~6 节。看懂「10 个快递同时签收」再往后翻。第 7 节以后是「套到真实程序」和附录。


1. 先用大白话说清楚

1.1 你现在的程序多半是这样

LOOP AT 内表. 调 BAPI 处理这一行. " 大约 1 秒 ENDLOOP.

1 万行就是大约 1 万秒。人在屏幕前干等。

1.2 「并行」想做的事

不要一条接一条。把 1 万行切成 10 包,每包 1000 行,让系统里空闲的对话窗口进程各拿一包同时干。

打个比方:

生活程序
你自己做 1000 份盒饭一个 LOOP 串行跑 BAPI
请 5 个厨师,每人 200 份5 个对话进程各处理一包
你是领班:分完盘子,站着等全做完CL_ABAP_PARALLEL负责分发和等待

ABAP 里说的「多线程」,不是Windows 那种线程。它是:

再开几个对话工作进程(DIA),每个进程跑你的同一段逻辑,只是数据不同。

对话工作进程可以先记成:系统里那种平时给你跑前台程序的工人。闲着的时候,可以借来干活。

1.3 什么时候值得并行

同时满足这三条,再考虑:

  1. 活很重:一条就要零点几秒到几秒(BAPI、远程接口)。
  2. 行和行基本不相干:A 物料扩工厂,不需要等 B 物料先成功。
  3. 一次数量大:几百、几千、几万行。

下面这些不要并行:

  • 循环里只是给字段赋值、改个字符串(太快,分发的时间比干活还长)
  • 第 2 行必须用第 1 行刚写进数据库的结果
  • 必须弹 GUI、读 Excel、GUI_UPLOAD(并行工人没有 SAP 窗口)

2. SAP 已经写好了「领班」

以前要自己写:RFC 函数、STARTING NEW TASK、自己数开了几个、自己WAIT、自己收结果。

现在用一个标准类就行:

CL_ABAP_PARALLEL

你只需要做两件事:

  1. 写一个小类:说明「一包数据怎么处理」。这个类要实现接口IF_ABAP_PARALLEL,里面只有一个方法,名字叫DO。
  2. 在主程序里:把数据切成几包,每包NEW一个小类,交给RUN_INST,然后等。

三个名字先混个脸熟(后面例子会反复出现):

名字把它当成干什么
CL_ABAP_PARALLEL领班决定请几个厨师、发盘子、等收工
IF_ABAP_PARALLEL厨师手册封面规定厨师必须会做的那一道工序:DO
你写的本地类,比如LCL_TASK一个厨师 + 他手上那一笼菜属性里放这一包数据,DO里炒这一包

DO没有IMPORTING/EXPORTING。
这一包的输入、输出,全部放在对象的属性(DATA)里。领班会把整个对象「打包寄」到另一个进程,那边拆开再调用DO。

「打包寄」的术语叫序列化。第一次听只记一句:

对象必须能被复印成一串字节寄走。所以属性里只能放数字、字符串、内表、结构,不能放 GUI 控件、Excel OLE 这种带窗口的东西。

接口源码一共就这么几行,没有隐藏魔法:

INTERFACE if_abap_parallel PUBLIC. INTERFACES if_serializable_object. " 声明:我可以被打包寄走 METHODS do. " 到了那边,就调这个方法 ENDINTERFACE.

3. 先抄一个能跑的最小例子(请务必跑一遍)

先不要想物料、BAPI。

想象网点柜台上堆了10 个快递:

  • 你一个人盖章:盖完 1 号再盖 2 号,一个 2 秒,一共 20 秒。
  • 请几个仓管同时盖:10 个件差不多同一时间盖完,大约 2 秒出头。

程序要做的就是这件事:每个快递一个任务,任务里假装忙 2 秒,然后写上「已签收」。

在测试系统新建可执行程序,整段粘贴、激活、F8。跑的时候旁边开事务SM50,能看到好几个人同时在盖章。

REPORT z_para_hello. "------------------------------------------------- " 1)一个对象 = 一个快递 " 单号是输入,签收结果是输出 "------------------------------------------------- CLASS lcl_express DEFINITION. PUBLIC SECTION. INTERFACES if_abap_parallel. METHODS constructor IMPORTING iv_bill TYPE i. " 创建时把单号塞进来 DATA mv_bill TYPE i. " 这件货的单号,比如 1、2、3 DATA mv_msg TYPE string. " 盖完章后写的话,比如「单号3已签收」 ENDCLASS. CLASS lcl_express IMPLEMENTATION. METHOD constructor. mv_bill = iv_bill. " 先记下来,先不干活 ENDMETHOD. METHOD if_abap_parallel~do. " 这句话运行在「另一个工人」身上,不是你当前这个窗口 WAIT UP TO 2 SECONDS. " 假装扫码、盖章,故意慢一点方便你去 SM50 看 mv_msg = |单号{ mv_bill }已签收|. ENDMETHOD. ENDCLASS. "------------------------------------------------- " 2)你当调度:把 10 个件分出去,然后等全盖完 "------------------------------------------------- START-OF-SELECTION. DATA lt_in TYPE cl_abap_parallel=>t_in_inst_tab. " 待分出去的快递清单 DATA lt_out TYPE cl_abap_parallel=>t_out_inst_tab. " 盖完拿回来的回执 DATA lo_one TYPE REF TO lcl_express. " 柜台上放 10 个件,单号 1~10。这时还没人盖章 DO 10 TIMES. APPEND NEW lcl_express( sy-index ) TO lt_in. ENDDO. " 开始分件。程序会停在这一行,直到 10 个都盖完(或有人失手) NEW cl_abap_parallel( p_percentage = 50 )->run_inst( EXPORTING p_in_tab = lt_in IMPORTING p_out_tab = lt_out ). " 把回执打在屏幕上 LOOP AT lt_out INTO DATA(ls_out). IF ls_out-message IS NOT INITIAL OR ls_out-inst IS NOT BOUND. WRITE: / '第', ls_out-index, '个件没盖成:', ls_out-message. CONTINUE. ENDIF. lo_one ?= ls_out-inst. " 回执上只写「一个工人」,转回我们的快递对象才能看单号 WRITE: / lo_one->mv_msg, ' 花了', ls_out-time, '秒'. ENDLOOP.

正常的话,大约 2~4 秒整屏刷完(不是 20 秒),类似:

单号1已签收 花了 2 秒 单号2已签收 花了 2 秒 ... 单号10已签收 花了 2 秒

如果还是要等大约 20 秒,说明几乎没请到帮手,去 SM50 看是不是只有一条对话进程。

3.1 对着代码看,就三件事

创建的时候不盖章,盖章发生在DO里

NEW lcl_express( 3 ) → 只是把「单号3」写在对象身上 run_inst → 把这个对象交给空闲工人 工人调用 DO → 等 2 秒,写下「单号3已签收」 对象寄回来 → 你从 mv_msg 里读到这句话

所以DO不需要IMPORTING:单号已经在MV_BILL里了。

run_inst这一行会卡住

不是「分完件你就去干别的」。10 个件全回来(或失败),这行才结束。你是调度,要在现场等。

回来的LT_OUT是回执本,一行一个件

字段人话
INST盖完寄回来的那个快递对象(失败时可能是空的)
INDEX当初清单里第几个(1 号、2 号…)
TIME这个工人盖这个件花了几秒
MESSAGE有字 = 这个件出事了(超时、程序 dump)

lo_one ?= ls_out-inst:回执上没写「这是快递」,只写「一个会做 DO 的工人」。要转回LCL_EXPRESS,才能看MV_MSG。

失败时不要转——东西可能没寄回来。所以先看MESSAGE和INST IS NOT BOUND。

3.2 用 SM50 确认「真的有几个人在盖」

F8 之后立刻打开SM50。这 2 秒里应能看到多条对话进程同时亮,程序名经常是RS_ABAP_PARALLEL_INST。那就是被借来的仓管。

想看得更久,把WAIT UP TO 2 SECONDS改成 5。看完改回去即可。


4. 运行时到底发生了什么

主程序所在的进程,下文叫协调进程(领班)。
被借来跑DO的进程,叫工作进程(厨师)。

你的报表(调度,站在柜台) │ │ NEW 出 10 个快递对象,每个身上写着单号 │ ▼ RUN_INST 开始(你站着等) │ ├── 把「单号1」递给工人 A ──► 盖章 2 秒 ──► 写上已签收 ──► 送回 ├── 把「单号2」递给工人 B ──► 盖章 2 秒 ──► ... └── 把「单号3」递给工人 C ──► ... (工人不够就排队,盖完一件再拿下一件) │ ▼ 10 个回执都齐了 │ RUN_INST 结束,你 WRITE 屏幕

有三句话,第一次学最容易忽略:

1. 工作进程是「新开的一次程序运行」。
它会重新加载你的报表。选择屏幕上勾的钩、你在屏幕填的工厂,不会自动出现在工作进程里。要带过去的东西,必须在NEW任务对象时塞进属性。

2. 两个进程的内表不是同一块内存。
协调进程的GT_OUT和线程里的GT_OUT各是各的。线程里改了,协调进程看不见,除非:

  • 写进任务对象属性,随对象寄回来;或
  • 线程里自己COMMIT写数据库,协调进程再查表。

3.EXPORT TO MEMORY(ABAP 内存)跨不过去。
那是当前会话的抽屉。工作进程是另一个会话,抽屉是空的。共享数据请放对象属性,或写数据库(例如INDX)。


5. 从「一个快递」改成「一包物料」(只改三处)

刚才一个任务 =一个快递单号。
真实批导里一个任务通常 =一包内表(比如 1000 条待扩展物料)。

还是盖章那套:工人还是工人,只是手里从「一个件」换成「一筐件」。

把任务类想象成填空:

CLASS lcl_task DEFINITION. PUBLIC SECTION. INTERFACES if_abap_parallel. METHODS constructor IMPORTING it_data TYPE 你的内表类型 " 这一包要处理的数据 is_flag TYPE 你的开关结构. " 选择屏幕勾了哪些视图,也要带上 METHODS get_results EXPORTING et_data TYPE 你的内表类型. PRIVATE SECTION. DATA mt_data TYPE 你的内表类型. DATA ms_flag TYPE 你的开关结构. ENDCLASS. CLASS lcl_task IMPLEMENTATION. METHOD constructor. mt_data = it_data. ms_flag = is_flag. ENDMETHOD. METHOD if_abap_parallel~do. " 下面三行是关键:工作进程里全局变量是空的,要自己灌 gt_out = mt_data. p_accou = ms_flag-p_accou. p_qm = ms_flag-p_qm. PERFORM 原来的单条或单包处理. " 里面调 BAPI、COMMIT 本包 mt_data = gt_out. " 处理结果带回来 ENDMETHOD. METHOD get_results. et_data = mt_data. ENDMETHOD. ENDCLASS.

主程序从「DO 10 TIMES」变成「按包 LOOP」:

" 1. 先把全部待处理数据放进 gt_all(和以前串行一样) " 2. 每 1000 条切一包,NEW 一个任务 DATA lt_pack TYPE 你的内表类型. DATA lt_in TYPE cl_abap_parallel=>t_in_inst_tab. DATA ls_flag TYPE 你的开关结构. ls_flag-p_accou = p_accou. " 屏幕上的勾,拷进结构 ls_flag-p_qm = p_qm. LOOP AT gt_all INTO DATA(ls_row). APPEND ls_row TO lt_pack. IF lines( lt_pack ) >= 1000. APPEND NEW lcl_task( it_data = lt_pack is_flag = ls_flag ) TO lt_in. CLEAR lt_pack. ENDIF. ENDLOOP. IF lt_pack IS NOT INITIAL. APPEND NEW lcl_task( it_data = lt_pack is_flag = ls_flag ) TO lt_in. ENDIF. " 3. 还是这一句 NEW cl_abap_parallel( p_percentage = 50 )->run_inst( EXPORTING p_in_tab = lt_in IMPORTING p_out_tab = DATA(lt_out) ). " 4. 收结果:和快递例子一样,先看失败,再 ?= 转回任务类

原来的 BAPI FORM 可以不重写。并行框架只负责换厨房;炒什么菜,还是你原来那盘。


6. 第一次实战只记这 6 条

① 一包里的行,不要抢同一把锁

同一物料号 + 同一工厂,不要同时出现在两个正在跑的包里。
否则两个对话进程一起改同一条主数据,会互等,甚至超时。

分包前按业务主键去重;同一主键只进一包。

② 选择屏幕的值,必须放进任务对象

工作进程看不到P_ACCOU、P_WERKS1。
漏传的表现非常像 bug:「我明明勾了会计视图,扩出来利润中心是空的」。其实线程里那个勾是初始值。

③ 每一包自己 COMMIT

工作进程跑完,对象就被收回。没提交的数据库更改会丢。
BAPI 成功后在这一包里BAPI_TRANSACTION_COMMIT。
包 A 成功、包 B 失败,互不影响——这正是并行的好处。

④ 包别切太碎,也别切太大

切法后果
一条一个任务寄对象的时间可能比 BAPI 还长
一包五万条一个对话进程占太久,容易超时,失败就整包重来
一包几百~一千条(BAPI 类)比较常见的起点

⑤ 先顺序跑通,再开并行

RUN_INST有个P_DEBUG。传到'X'时,不请厨师,就在当前程序里一个一个调DO。这样你才能下断点。

lo_par->run_inst( EXPORTING p_in_tab = lt_in p_debug = 'X' " 开发时打开;测并行时去掉 IMPORTING p_out_tab = lt_out ).

⑥ 很短的活不要并行

官方说得很直白:把数据搬到另一个对话进程是要花时间的。
赋值、拼字符串这种,并行只会更慢。


7. 对照:物料扩展程序 ZMMU002S 是怎么套的

看懂第 3~5 节之后,这段只是「一个快递换成一包物料」。不必一次记完所有表名。

7.1 它在并行什么

从源工厂把物料主数据扩到目标工厂。一条大约要:

  • BAPI_MATERIAL_SAVEDATA
  • 必要时质量视图 BAPI
  • 必要时 MRP 区域函数

一条大约 1 秒,一次上万条,所以值得并行。
读 Excel 仍然在前台做(要 SAP 窗口),读完再并行。

7.2 和最小例子的对应关系

快递例子ZMMU002S
LCL_EXPRESSLCL_MAT_PARALLEL(写在同一个报表里的本地类)
MV_BILL一个单号MT_DATA:这一筐待扩展物料
没有开关MS_PARAM:销售/采购/会计等勾选
DO里等 2 秒再写「已签收」DO里灌全局变量,再PERFORM MATERIEL_IMPORT
10 个快递 = 10 个任务每 1000 条(P_PKG)= 1 个任务
RUN_INST同样,P_PERCENTAGE = 60
屏幕WRITE签收结果从对象GET_RESULTS,失败则按批次号更新日志表

任务类的DO只有三步,和填空模板一样:

METHOD if_abap_parallel~do. init_log_records( ). " 准备本包日志内表 execute_import( ). " 参数写回 P_* / GT_*,再调原来的导入 save_log_final( ). " MODIFY 日志表并 COMMIT ENDMETHOD.

EXECUTE_IMPORT里把属性倒回报表全局变量——因为原来的 FORM 读的就是这些全局变量:

p_accou = ms_param-p_accou. p_qm = ms_param-p_qm. " ... 其它勾选同样抄一遍 gt_tq34 = mt_tq34. " 质量类型,协调进程查一次带进来 gt_mdma = mt_mdma. " MRP 区域是否已存在,也是带进来 gt_out = mt_data. PERFORM materiel_import USING gt_mdma. mt_data = gt_out.

7.3 分包用了批次号

每条待处理数据带一个BATCHNO,例如20260924-170000-0001。
结构里BATCHNO必须是第一个字段,才能用AT NEW batchno把同一包切出来(AT NEW会看这个字段左边的所有字段)。

批次号还有第二个用处:某个工作进程短 dump 了,对象回不来,协调进程仍可:

UPDATE zmmt146_log SET status = 'E' msg_mm = ls_out-message WHERE batchno = 这一包的批次号.

把「整包任务挂了」和「某一条 BAPI 报错」分开记。

7.4 只读表不要每个线程查一遍

表谁查为什么传入
TQ34程序开头查一次每个线程质量视图都要用
MDMA开线程前按本批物料查一次已经有 MRP 区域就跳过创建

这些内表作为任务属性被一起寄走。不要把全厂无关数据塞进每一个包。

7.5 用户要关窗口时:作业里面再并行

RUN_INST会让当前这个进程一直等到全部包结束。
用户如果直接把 GUI 关了,领班死了,厨师也会被收掉。

所以勾了后台执行时:

  1. 前台只负责读 Excel,把物料号写入数据库簇表INDX
  2. JOB_OPEN+SUBMIT 本程序 VIA JOB
  3. 用户可以关窗
  4. 后台作业当领班:取回物料号、生成待处理内表、再RUN_INST

作业是后台进程(BTC),RUN_INST仍然去借对话进程(DIA)。
SM37 里看到的是作业总时间;SM50 里才能看到几条 DIA 在真正跑 BAPI。


8. 怎么判断「真的并行了」

你看到的说明
SM50 同时有多条RS_ABAP_PARALLEL_INST并行在干活
SM50 长期只有 1 条几乎没并行:百分比太低、DIA 不够、或P_DEBUG还开着
SM37 显示 2 小时那是领班等待的墙钟时间,不是「一个进程串行了 2 小时」
50 个包、同时只有 5 个厨师总时间大约是「10 波 × 每包时间」,不是 50 倍加速

粗算:

总时间 ≈ 向上取整(包数 ÷ 同时在跑的DIA数) × 一包时间

5 万条、每包 1000 条 → 50 包。
同时 5 个 DIA、每包 3 分钟 → 大约 30 分钟,而不是 3 分钟。
若 SM50 只有 5 个 DIA 可借,把百分比从 60 调到 80 也变不出更多厨师。


9. 领班的两个常用旋钮

第一次只用这两个:

DATA(lo_par) = NEW cl_abap_parallel( p_percentage = 50 " 最多占用「可借给并行的对话进程」的一半,默认就是 50 p_timeout = 0 " 0 = 不另设超时,沿用系统限制 ). lo_par->run_inst( ... ).

P_PERCENTAGE不是「占全部对话进程的 50%」。
系统会先留一些对话进程给真正的前台用户(防止别人登不进去),剩下那部分才拿来并行。再在这上面乘百分比。

生产上不要开到 100。物料扩展这种重活,案例里用了 60,已经略激进。

P_TIMEOUT不要随手填 60。
一包 1000 条 BAPI 可能跑很多分钟,填 60 秒会把正常包全部判失败。

其它参数(只用本服务器、最多几个任务、一挂就停)放在文末附录,第一次可以不看。


10. 你的系统够不够用这套写法

在 ADT 或 SE24 打开类CL_ABAP_PARALLEL,看有没有方法RUN_INST。

看到什么怎么办
有RUN_INST按本文写(一般是 7.54 及以上,S/4 常见)
只有RUN,没有RUN_INST系统偏老。要用另一种「自己把数据打成 XSTRING」的写法,见附录 C
类都没有基线太老,继续用传统 aRFC,或让 Basis 看 Note 2791374 能否下发

案例程序所在系统是SAP_BASIS 7.56,有RUN_INST。


11. 学完后动手的顺序

  1. 把第 3 节快递程序跑通。十个件应大约 2 秒结束,SM50 里能看到多个人同时盖章。
  2. 打开P_DEBUG = 'X',对DO下断点,确认能停住(这时会变回一个一个盖,大约 20 秒)。
  3. 把「一个单号」换成「你的内表的一小包」,DO里调现有 FORM。
  4. 确认这一包在调试模式下 BAPI + COMMIT + 日志都对。
  5. 关掉P_DEBUG,P_PERCENTAGE先 30 再 50。
  6. 用 SM50 数实际有几个工人,再决定一筐装多少条。

不要一上来就把 5 万条、Excel、后台作业、日志表一起改。那是第 7 节的完整形态,不是第一天的作业。


附录 A:构造参数全表(需要调优再看)

7.56 系统里CL_ABAP_PARALLEL构造方法:

参数第一次要不要管含义
P_PERCENTAGE要占用可借 DIA 的百分比,默认 50
P_TIMEOUT通常 0单个任务最多跑多少秒
P_NUM_TASKS可选同时跑的任务上限。和百分比一起传时,实际取更保守的那个
P_LOCAL_SERVER一般不传'X'= 只用当前应用服务器。任务若碰本机文件再打开
P_NUM_PROCESSES不要用类注释写明已过时
P_ABORT_ON_ERROR可选有任务因 RFC/短 dump 挂掉时,剩下的任务不再进DO

另外还有FORK/JOIN(不必等全部结束就能收已完成的包)、后台提交类方法。那是进阶,第一次做批导用不到。RUN_INST是等到全部结束才返回。


附录 B:回来的结果行怎么判断

LOOP AT lt_out INTO DATA(ls_done). IF ls_done-message IS NOT INITIAL OR ls_done-inst IS NOT BOUND. " 任务级失败:整包没正常跑完 " 用 ls_done-index 找回当初那一包,去更新日志 CONTINUE. ENDIF. DATA(lo_task) = CAST lcl_task( ls_done-inst ). lo_task->get_results( IMPORTING et_data = DATA(lt_part) ). " 业务级失败(某条 BAPI 报 E)已经写在 lt_part 或日志表里 ENDLOOP.

两种失败不要混:

  • 任务失败:厨师把灶台烧了(dump、超时)。对象可能没了。
  • 业务失败:厨师把菜做完了,但这道菜盐放多了(BAPI 返回 E)。对象还在。

附录 C:没有 RUN_INST 时的另一条路(了解即可)

更老的系统只有RUN:自己把每包打成XSTRING,任务类继承CL_ABAP_PARALLEL并重写DO,在DO里再解开。样板代码明显更多。能用RUN_INST就不要走这条。

社区博文Using class CL_ABAP_PARALLEL for mass parallel dialog work processes(Dan Mazurowski)有完整RUN示例。


附录 D:参考

  • 事务 SE24 / ADT:类CL_ABAP_PARALLEL上按 F2,看 ABAP Doc(比 Help 网页全)
  • SAP Help Portal 搜Parallel Processing+CL_ABAP_PARALLEL
  • SAP Note 2791374(类下发到 7.50)、2880858(RUN_INST从 7.54 起,不下放到更低版本)
  • 接口IF_ABAP_PARALLEL:继承IF_SERIALIZABLE_OBJECT,方法只有DO
  • SM50 里的函数名RS_ABAP_PARALLEL_INST:用来确认并行在跑,不要当业务 API 去调

结束前再重复一遍

你真正要写的,永远是这三块:

  1. 一个任务类:属性 = 一包数据 + 配置;DO= 处理这一包。
  2. 主程序切包:NEW出 N 个对象。
  3. 一句RUN_INST:卡住直到全部结束,再按成功/失败收卷。

快递例子就是这三块。物料扩展也是这三块,只是一筐更重、多传了选择屏幕和两张缓存表、多写了一张日志表。先把 10 个快递跑通,再往筐里塞 BAPI。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 6:11:08

React Native 鸿蒙跨平台开发实战:文件路径处理工具从零落地

这两年做跨端开发的人,应该都感觉到一个明显的变化:鸿蒙不再只是“安卓的一个变种”,而是一个需要单独对待的新目标平台。我身边不少团队都在评估 React Native 跑鸿蒙的可行性,说实话,这个方向在一年多前还不太敢碰—…

作者头像 李华
网站建设 2026/9/26 6:10:41

VoNR高掉话排查实战:从信令分段到根因定位的端到端方法

简介:这份PDF面向5G网络优化工程师、核心网与无线维护人员,聚焦VoNR端到端高掉话这一典型疑难问题,提供从指标异常发现到根因定位、优化验证的完整排查思路。资源为单文件PDF,压缩包约1.81MB,内容以案例文档形式呈现&a…

作者头像 李华
网站建设 2026/9/26 6:10:37

5GNR理论笔记实战指南:从帧结构、numerology到BWP与参考信号

简介:这份《5GNR学习笔记-理论v1.0.pdf》面向通信工程、无线网络优化方向的初学者与进阶读者,系统梳理5G新空口的基础理论框架,帮助读者建立从网络架构到物理层的完整认知。内容涵盖NR总体架构与功能划分,包括gNB与ng-eNB节点、AM…

作者头像 李华
网站建设 2026/9/26 6:10:34

从Harness到认知工程:重构AI Agent的底层思维范式

1. 项目概述:从 harness 工程到认知工程,不是换名字,是重构底层思维范式“Agent: 将 harness 工程升级到认知工程”——这个标题乍看像一句技术口号,实则是一次静默却剧烈的范式迁移。我带团队落地过 7 个中大型 AI 工程项目&…

作者头像 李华
网站建设 2026/9/26 6:09:32

Matlab环境下消防搜救智能体仿真:动态路径规划与目标概率检测

1. 为什么我用智能体模拟消防搜救:真实火场约束下的仿真思路楼里浓烟已经蔓延到三层,每个房间的烟雾传感器都在报警,已知被困人员还剩两名没有找到,如果搜救路线按直线走进去,很可能被高温气流封住退路。这是我在做消防…

作者头像 李华
网站建设 2026/9/26 6:08:40

SQL常用语言速查:从查询语法到慢SQL优化与SQL Server避坑

用了几年SQL之后我最大的感受是:不管你是做后端、搞数据分析,还是兼职运维数据库,真正需要“背下来”的常用SQL就那么几块。剩下的绝大多数场景,都是在这几个基础语法上排列组合而已。这篇汇总里我不会事无巨细地罗列手册内容&…

作者头像 李华