simjava2实战:离散事件仿真建模与M/M/1排队模型全解析
简介面向云计算、网格计算与分布式系统研究者的SimJava2离散事件驱动仿真资料包系统讲解事件调度、时间戳处理、优先级队列、模块化建模、统计分析、可视化界面等核心机制并围绕资源调度、服务性能评估、故障恢复和网格任务调度等典型场景完整展示从仿真建模到结果分析的实践路径。压缩包共465个文件以227个class字节码、110个java源码和97个html文档为主体辅以12个txt说明、3个Python脚本、2个jar包以及Makefile、配置和日志文件整体大小4.68MB目录结构清晰便于按源码、文档、脚本和运行输出分类查阅。包内提供SimTest示例程序可直接运行并修改测试用例帮助读者快速上手SimJava2深入理解离散事件驱动机制在大规模计算环境中的实际应用。已有310人学习下载适合希望掌握仿真工具并独立开展实验的初学者与研究人员。1. simjava2 是什么离散事件仿真从入门到跑通的第一个 Demo第一次跑通 simjava2 的 Hello World 时你大概率会嫌它啰嗦要先写实体类、建端口、再手动连接端口最后才看到仿真时钟推动事件往前走。但它恰恰是这类离散事件仿真包里把调度逻辑暴露得最清楚的一个。simjava2 是一个纯 Java 的离散事件仿真框架核心模型是「实体—端口—事件」实体自己决定 hold耗时间、发送事件、等待事件调度器用仿真时间把它们串起来。适合三类人——学生做课设、工程师做容量估算、研究者验证排队策略。资源通常就是一个 jar 加 javadoc 和几个示例配置好 classpath 就能跑读起来比 SimPy 更贴近底层调度概念。2. 安装与工程骨架三步把 simjava2 跑起来simjava2 不像现代框架那样有一堆依赖要装你拿到的资源包里就一个核心 jar 和几个示例目录。难点不在安装而在把「实体怎么注册、端口怎么连、事件怎么收」这套骨架看懂。这一章我直接给你一个能编译、能跑、能停下来的最小工程然后解释每一行在干什么。2.1 包结构、运行时依赖它其实只是一个小 jar解压资源包后你会看到类似这样的目录结构路径内容作用simjava2.jar核心类包名以eduni开头编译和运行都要依赖Javadoc/API 文档查方法签名和生产笔记examples/bank、cat、oil 等示例工程新手最好的起步参考核心包里的关键类只有五个Sim_system全局调度器静态方法、Sim_entity实体基类你的业务逻辑写在body()里、Sim_port端口、Sim_event事件、Sim_random随机数工具当然你也可以直接用java.util.Random。实体在 simjava2 内部是以 Java 线程方式跑的但调度器用仿真日期把它们串成协作式协程所以你写的body()看起来像顺序代码实际上每次sim_hold()都会把控制权交回调度器。经常有人问要不要装额外的依赖答案是不用。simjava2 不依赖第三方库JDK 8 就能跑。我见过很多编译报错最后发现是把 1.x 和 2.x 的包搞混了或者 jar 没进 classpath没有一个是缺第三方包导致的。提示simjava2 有 1.x 和 2.x 两个常见版本方法签名略有差异。下面代码以 2.x 的eduni.simjava包为准。如果你拿到的包里没有initialise(long, boolean)用javap eduni.simjava.Sim_system看一下真实签名按你的版本调整即可。2.2 最小骨架主类、实体类与端口连接给你一个最简却能完整跑完的 demo一个 Source 发 5 个事件一个 Sink 收满 5 个后叫停仿真。这样你第一次跑就不会遇到「所有实体都在等事件」的死锁陷阱。import eduni.simjava.*; class Source extends Sim_entity { private Sim_port out; private int total; public Source(String name, int total) { super(name); // 实体的名字注册和连端口时要用 this.total total; out new Sim_port(Out); add_port(out); // 把端口登记到当前实体 } public void body() { for (int i 0; i total; i) { // 0.0 表示立即投递到 out 端口 sim_schedule(out, 0.0, i, null); sim_hold(1.0); // 每隔 1 个仿真时间单位发一个 } // body() 走到这里Source 这个实体就结束了 } } class Sink extends Sim_entity { private Sim_port in; private int count 0; private int expected; public Sink(String name, int expected) { super(name); this.expected expected; in new Sim_port(In); add_port(in); } public void body() { Sim_event e new Sim_event(); while (count expected) { sim_get_next(e); // 阻塞等待事件到来 count; sim_trace(1, received # count tag e.get_tag()); } sim_system.stop(); // 主动终止仿真 } } public class MinimalMain { public static void main(String[] args) { Sim_system.initialise(); // 初始化调度器 Sim_system.register_entity(new Source(src, 5)); Sim_system.register_entity(new Sink(sink, 5)); Sim_system.link_ports(src, Out, sink, In); Sim_system.run(); } }这段代码的正确姿势是先初始化调度器再注册实体然后用link_ports把源实体的Out端口连到目标实体的In端口最后run()启动。link_ports的参数顺序是「源实体名、源端口名、目标实体名、目标端口名」我见过不少人把源和目标写反结果事件直接投递到无人接收的端口仿真秒结束。sim_schedule(out, 0.0, i, null)里的三个参数分别是端口、延迟和事件 tag。这里我把i当作事件类型标识用null是不携带业务数据。要注意sim_hold(1.0)消耗的是仿真时间不是真实时间如果你的仿真模型里一个任务要服务 2 秒这里写的就是sim_hold(2.0)。2.3 常见做法用脚本编译、运行与读 trace拿到本资源的示例工程里面有现成的Makefile或.bat。没有的话手动编译也就三行# 假设 simjava2.jar 在 lib/ 目录下源码在 src/ 下 javac -cp lib/simjava2.jar -d out src/MinimalMain.java java -cp lib/simjava2.jar:out MinimalMain跑起来之后你会在控制台看到类似这样的输出[0.000] src: 生成任务 #1 [1.000] sink: received #1 tag0 [2.000] sink: received #2 tag1sim_trace(1, ...)的第一个参数是 trace 级别只有级别小于等于Sim_system.initialise()里开的级别才输出。我一般会固定用级别 1 打关键信息级别 2 打细粒度调试方便定位端口丢事件的问题。关于initialise的常见变体按需选调用方式含义Sim_system.initialise()默认随机种子每次结果不同Sim_system.initialise(long seed)固定种子结果可复现Sim_system.initialise(long seed, boolean trace)固定种子并开启内部 trace跑示例工程时尽量先自己手动javac一遍不要直接依赖 IDE 的自动解析。很多老项目里classpath配置是相对路径换目录就崩你亲手敲一遍能少踩一半坑。3. 核心概念与建模套路实体、端口、事件调度里的三个关键动作上一章的最小骨架跑通后基本框架已经立住了。这一章把 simjava2 的三个核心动作讲透实体的body()怎么工作、事件怎么通过端口流动、以及怎么用一个完整的 M/M/1 排队模型把三者串起来。3.1 实体的生命周期与 body() 方法每个实体类的入口是body()它在仿真时刻 0 开始执行。你写的代码像是同步运行但每次调用sim_hold()时实体会让出 CPU调度器把仿真钟拨到下一个事件时刻再唤醒它。这就是 simjava2 最吸引我的地方你用写多线程的逻辑去写仿真但不用碰任何锁和信号量。实体生命周期有三种结束方式body()正常返回实体变 inactive之后不会再有它的事件。整个系统被sim_system.stop()强制终止。调度器发现所有实体都在等待不可能到达的事件判定死锁并结束。第三种情况就是新手最容易翻车的地方。我见过很多同学的代码里 Server 实体写了while (true)等着收任务Generator 发完活就返回了结果 Server 永远等不到下一个事件整个程序看起来像卡死。经验做法是给每个「无限等待」的实体配一个合理的结束条件或者在最下游放一个 Sink 实体由它计数并主动stop()。3.2 事件模型端口、tag、data 的交互规则simjava2 的事件Sim_event里有几个关键字段你可以当作一张表来记字段含义设置方式tag事件类型标识int类型sim_schedule(port, delay, tag, data)data携带的业务对象任意Object同上没有就传nulltime事件投递的仿真时刻由delay加上当前sim_time()自动算出sender发送实体名调度器填充只读destination接收实体名调度器填充只读这里有两个容易忽略的约束。第一tag 是int想在事件里带个字符串或者自定义对象必须走 data 字段。第二link_ports建立的是点对点单向链路你只能从 out 端口发、在 in 端口收要做广播就得自己建多个 out 端口分别连接。同一个仿真时刻到达的多个事件处理顺序受内部调度器影响写业务逻辑时不要依赖「同一 tick 谁先谁后」。我在单机跑还好换到多核机器上出现过统计结果漂移后来把所有「按到达顺序累计」的逻辑改成「按 tag 分流」问题才稳定下来。3.3 一个 M/M/1 队列实例Generator、Server、Sink 完整代码这一节我拿最经典的 M/M/1 排队系统练手任务到达间隔服从均值为 1.0 的指数分布服务时间服从均值 0.8 的指数分布负载率 ρ 0.8 1系统能稳定。三个实体Generator 产生任务、Server 处理、Sink 收集统计并终止仿真。先定义一个Job数据对象用来跨实体传递任务 ID 和几个时间戳class Job { int id; double genTime; // 任务创建时刻 double serviceStart; // 服务开始时刻由 Server 填写 Job(int id, double genTime) { this.id id; this.genTime genTime; } }Generator 的任务是产生任务并按指数间隔发送到 Serverclass Generator extends Sim_entity { private Sim_port out; private int jobsToSend; private double meanInterval; private java.util.Random rng; public Generator(String name, double meanInterval, int jobsToSend, long seed) { super(name); this.meanInterval meanInterval; this.jobsToSend jobsToSend; out new Sim_port(Out); add_port(out); rng new java.util.Random(seed); } public void body() { for (int i 0; i jobsToSend; i) { sim_schedule(out, 0.0, 1, new Job(i, sim_time())); // 指数间隔-meanInterval * ln(1 - U) double interval -meanInterval * Math.log(1.0 - rng.nextDouble()); sim_hold(interval); } } }sim_schedule里的延迟设为 0.0表示任务立刻进入 Server 的输入端口。sim_time()是实体内部可直接调用的方法返回当前仿真时刻我用它记录任务的出生时间。生成间隔用逆变换法采样指数分布注意1.0 - rng.nextDouble()是为了避免nextDouble()返回 0 导致Math.log(0)出现负无穷。Server 负责服务并给 Job 打上服务开始时间class Server extends Sim_entity { private Sim_port in; private Sim_port out; private double meanService; private java.util.Random rng; public Server(String name, double meanService, long seed) { super(name); this.meanService meanService; in new Sim_port(In); out new Sim_port(Out); add_port(in); add_port(out); rng new java.util.Random(seed); } public void body() { Sim_event e new Sim_event(); while (true) { sim_get_next(e); // 没有任务就挂起 Job job (Job) e.get_data(); // 取出业务数据 job.serviceStart sim_time(); double service -meanService * Math.log(1.0 - rng.nextDouble()); sim_hold(service); // 模拟服务耗时 sim_schedule(out, 0.0, 1, job); } } }Sink 收集每个任务的等待时间和响应时间class Sink extends Sim_entity { private Sim_port in; private int expected; private int count 0; private double totalWait 0.0; private double totalResponse 0.0; public Sink(String name, int expected) { super(name); this.expected expected; in new Sim_port(In); add_port(in); } public void body() { Sim_event e new Sim_event(); while (count expected) { sim_get_next(e); Job job (Job) e.get_data(); double wait job.serviceStart - job.genTime; // 排队时间 double resp sim_time() - job.genTime; // 响应时间 totalWait wait; totalResponse resp; count; sim_trace(1, job job.id wait wait); } System.out.printf(jobs%d avgWait%.4f avgResp%.4f%n, count, totalWait / count, totalResponse / count); sim_system.stop(); } }Main 类里把它们注册、连端口、跑起来public class MMcDemo { public static void main(String[] args) { Sim_system.initialise(42, false); // 固定种子不开内部 trace Generator gen new Generator(Gen, 1.0, 20000, 10001); Server srv new Server(Srv, 0.8, 20002); Sink sink new Sink(Sink, 20000); Sim_system.register_entity(gen); Sim_system.register_entity(srv); Sim_system.register_entity(sink); Sim_system.link_ports(Gen, Out, Srv, In); Sim_system.link_ports(Srv, Out, Sink, In); Sim_system.run(); } }参数含义如表所示跑的时候可以按需调整参数示例值说明meanInterval1.0到达间隔均值到达率就是 1.0meanService0.8服务时间均值负载率 ρ 0.8/1.0 0.8jobsToSend20000总任务数样本量越大统计越稳各个 seed奇数偏移不同实体用不同种子避免随机数流重叠ρ 0.8 时M/M/1 的理论平均排队等待时间W_q ρ * E[S] / (1-ρ) 0.8 * 0.8 / 0.2 3.2响应时间T W_q E[S] 4.0。你跑出来的avgWait应该逼近 3.2avgResp逼近 4.0。如果量级差得离谱大概率是下面的坑踩中了直接翻到第 5 章。4. 参数配置与统计输出让仿真结果可信模型能跑只是第一步仿真结果能不能让人信是另一回事。这一章讲三个最影响可信度的参数控制随机数种子怎么分配、数据什么时候该收、统计结果怎么报才有意义。4.1 随机数种子三个 seed 各管什么在 M/M/1 例子里出现了两个层级的 seedSim_system.initialise(42, false)里的 42 是系统层种子Generator 和 Server 构造时的 10001、20002 是实体层种子。两者的分工要弄清楚。seed 位置影响范围建议Sim_system.initialise(seed, trace)调度器内部随机数影响同一时刻多事件的拆平顺序固定即可不必频繁改实体自己的Random(seed)影响该实体的到达/服务时间抽样每个实体分配独立种子不要共用同一个实例同一种子在不同 JDK 或多核环境下可能出现轻微统计漂移原因是 JVM 线程调度会影响同 tick 事件顺序。这就是为什么我建议把业务统计按 tag 分流而不是依赖事件到达顺序。如果要做严格的复现实验最高规格的做法是自实现一个线性同余随机数发生器彻底绕开java.util.Random的实现差异。4.2 预热期与运行时长什么时候开始收数排队系统是空系统起步的队列需要一段时间才能进入稳定状态。如果你从第 1 个任务就开始累计等待时间前几百个任务的平均值会把整体统计拉低这在 ρ 接近 1 时特别明显。常见的处理办法是「热身后再生」即跳过大队列还没建立起来的前一段数据。一个实用做法是把 Sink 的统计区分为预热段和正式段class WarmupSink extends Sim_entity { private static final int WARMUP_JOBS 1000; // 前 1000 个任务不计入统计 private Sim_port in; private int expected; private int count 0; private double totalWait 0.0; public WarmupSink(String name, int expected) { ... } public void body() { Sim_event e new Sim_event(); while (count expected) { sim_get_next(e); Job job (Job) e.get_data(); double wait job.serviceStart - job.genTime; if (count WARMUP_JOBS) { totalWait wait; } count; } System.out.printf(avgWait%.4f%n, totalWait / (count - WARMUP_JOBS)); sim_system.stop(); } }参数WARMUP_JOBS设多少取决于收敛速度。ρ 0.5 时 500 个就够了ρ 0.9 时建议至少 5000。我的习惯是先跑一次不预热的结果再跑一次预热的两个数字差超过 5%就说明预热段太短把WARMUP_JOBS往上加。运行时长则用「总任务数」控制比用「仿真时长」控制更直观因为你明确了要多少个样本。4.3 统计口径与置信区间别只报一个平均数单个仿真跑出来的平均等待时间本质上是随机变量的一次实现。把 20 个不同种子的运行结果放在一起才能看出稳定性。我一般会对每个参数点做 10 次重复仿真把每次的平均值存进数组再算均值和 95% 置信区间。下面这个工具方法可以直接抄去用public static double[] meanCI(double[] xs) { int n xs.length; double mean 0; for (double x : xs) mean x / n; double var 0; for (double x : xs) { double diff x - mean; var diff * diff; } var / (n - 1); double se Math.sqrt(var / n); return new double[] { mean, 1.96 * se }; }返回值是{均值, 95% 置信区间半宽}样本量达到 10 次以上用正态分布的 1.96 近似完全够用。报结果的时候写成「4.02 ± 0.11」比单纯报「4.02」专业得多复现实验的人也更容易判断差异是不是真差异。理论对照也建议做成一张表贴在你报告里ρ理论 W_q理论响应时间 T0.50.801.600.83.204.000.97.208.00如果仿真出来的W_q偏离公式值超过 5%先查预热和随机数再回头查代码逻辑而不是急着调参数去「配平」结果。5. 避坑与常见问题排查五个翻车现场这里写的每条都是我和同事实际踩过的坑按「现象 → 原因 → 解决」给你排好。你在跑示例或自己的模型时按图索骥就行。5.1 现象仿真瞬间结束没输出任何事件现象run()秒回控制台干干净净或者只有初始 trace 没有事件 trace。原因最常见的是实体注册少了或者link_ports把源和目标写反。事件发出后投递到没有接收者的端口调度器认为系统里没有活实体直接收场。另一个隐蔽原因是 Sink 的expected和 Generator 的total不一致导致 Sink 等不到足够事件就触发了结束分支。解决先剪一条最简链路只留 Source 和 Sink跑出 trace 再往上加实体。加实体的过程中每加一个端口连接就打印一行连接关系确认link_ports的前两个参数是「源实体名、源端口名」后两个是「目标实体名、目标端口名」。实体名不要重复端口名在同一实体内部不要重复。5.2 现象仿真卡死线程像是在互相等现象程序不退CPU 一直被占满但仿真时间停在某个值trace 不再前进。原因典型死锁。最常发生在 Server 实体用while (true)做sim_get_next()等任务而上游 Generator 已经body()返回或者 Sink 已经stop()但 Server 这个实体还挂在等待队列上。simjava2 对这种「不会有人再发事件」的等待没有自动熔断机制。解决给每个无限等待的实体设计明确的终止路径。我一般会在 Sink 收到最后一个任务时额外向 Server 发一个带特殊 tag 的「下班事件」Server 收到这个 tag 就return结束body()。这样所有实体都能自然退出而不是依赖sim_system.stop()硬停。多实体模型里这条「终止事件链」值得画出来再写代码。5.3 现象平均等待时间总是偏大 30%现象跑了 20000 个任务avgWait比理论值 3.2 明显偏大而且调大多次种子都一样。原因最常见的原因是没做预热空系统起步导致前段队列没建立但你的统计是从第一个任务开始的计算口径反而把前面偏高的「单个任务」也算进去了。另一个隐蔽原因是 Generator 把任务的genTime记成 0 而不是sim_time()导致每个任务的等待时间虚增了整整一个到达时刻。解决按 4.2 的做法跳过预热段并且在Job构造函数里强制用sim_time()打时间戳不要在外面用系统时钟或 0 占位。我习惯在 Sink 里加一个断言检查所有job.serviceStart job.genTime一旦发现负的等待时间立刻能定位到时间戳打错位置。5.4 现象换了 JDK 之后结果对不上现象同样的种子、同样的代码在一台机器上跑出 3.21另一台机器跑出 3.28再跑一次又变。原因java.util.Random本身是可复现的但 simjava2 调度器对同一仿真时刻的多个事件处理顺序受 JVM 线程调度影响多核机器差异尤其明显。如果统计代码依赖「事件到达顺序」结果就会漂移。解决首要原则是不写依赖同 tick 顺序的业务逻辑。第二把 tag 当作「事件类型」data 当作「业务数据」按类型累加而不是按到达顺序累加。第三如果实验要求跨机器完全复现就自己实现一个简单的线性同余随机数生成器替换实体里的java.util.Random并把仿真日历里的多事件排序逻辑钉死在代码里。5.5 现象运行时报 ClassCastException现象java.lang.ClassCastException: java.lang.Integer cannot be cast to Job堆栈指向 Sink 里的(Job) e.get_data()。原因sim_schedule(port, 0.0, i, null)的 data 是null但接收端脚本里却强转成了Job或者你从某个示例里复制了sim_schedule(port, 0.0, tag)重载方法这个版本根本不带 data 参数data 字段默认就是null。解决统一链路里所有sim_schedule调用的 data 类型。我自己的写法是Generator 发new Job(...)Server 收到后补字段再转发同一个Job对象全程保持强类型。接收侧加一道保险Object data e.get_data(); if (data instanceof Job) { Job job (Job) data; // 正常统计 } else { sim_trace(1, unexpected data type: data); }这道保险在调试混用旧示例代码时能救你一命。6. 进阶把 simjava2 变成批量实验引擎模型单独跑一遍只是开始真正有价值的实验是一批参数点连续跑完然后对比曲线。6.1 参数扫描20 个负载点一把跑出来把MMcDemo的 main 改造成从命令行接收参数的形式负载率由外部传入。到达间隔固定为 1.0服务均值 ρ × 到达间隔那么命令行传 ρ 即可public class ExpMain { public static void main(String[] args) { double rho Double.parseDouble(args[0]); // 负载率 0.5 ~ 0.9 int jobs Integer.parseInt(args[1]); // 总任务数 long baseSeed Long.parseLong(args[2]); // 基础种子 // 每个参数点用不同偏移种子防止多条实验链相关 long seed baseSeed Math.round(rho * 1000); // 以下结构与 MMcDemo 相同meanService rho * 1.0 } }再用一个 shell 循环把 20 个负载点都跑一遍输出到独立文件for rho in $(seq 0.50 0.02 0.90); do java -cp simjava2.jar:. ExpMain $rho 20000 42 rho_$(echo $rho | tr . _).txt done跑完后用 awk 或者你顺手的脚本把所有平均等待时间汇总成一行 CSV最后画一条「ρ 对 W_q」的曲线。这条曲线如果和理论公式曲线重合度高比单独汇报一个点有说服力得多。6.2 验证仿真可信度的小习惯我现在每次做这类仿真实验都会把 M/M/1 这种有闭式解的场景当作回归测试用例任何新模型上线前先跑一版已知答案的基准确认框架参数和统计口径没被带偏。做参数扫描时每个点至少用 5 个不同种子重复结果里必须带上置信区间。输出文件里也顺手带上仿真时钟结束时刻和总事件数这两个值能帮你快速发现死锁或过早终止的异常。从那以后我每次跑 simjava2 前都会强制走一遍这条检查先跑最小链路看 trace再固定三个种子做复现再丢 10% 预热样本最后才敢把统计数字贴进报告里。就算这样M/M/1 的结果偶尔还是会提醒我仿真门槛低不代表结果可信。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

公式识别如何做?OpenCV预处理与深度学习模型全流程解析

公式识别如何做?OpenCV预处理与深度学习模型全流程解析

公式识别这个选题,最近在毕设里确实很常见。看到题目里有“深度学习”“OpenCV”“公式识别”这几个词,很多同学第一反应是找个现成的开源模型跑一跑,把测试集准确率截图放论文里就完事。但真上手之后会发现:公式识别和普通文字OC…

2026/10/16 2:14:50 阅读更多 →
ok-ww 鸣潮一键日常与刷声骸:睡醒前跑完

ok-ww 鸣潮一键日常与刷声骸:睡醒前跑完

ok-ww 鸣潮一键日常与刷声骸:睡醒前跑完 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves ok-ww 是一款鸣潮后台自动化工…

2026/10/16 2:13:50 阅读更多 →
100 万 token 上下文实测:Step 5 Preview 一次能吞下多大的工程

100 万 token 上下文实测:Step 5 Preview 一次能吞下多大的工程

100 万 token 上下文实测:Step 5 Preview 一次能吞下多大的工程 【免费下载链接】Step-5-Preview Step 5 Preview 是阶跃星辰面向智能体工作打造的旗舰模型。该模型在软件工程和专业知识工作领域均展现出前沿级性能,尤其在金融领域表现突出。 Step 5 Pre…

2026/10/16 2:13:50 阅读更多 →

最新新闻

平台人员排查租户故障,怎样临时授权?最小访问范围、限时撤销与审计

平台人员排查租户故障,怎样临时授权?最小访问范围、限时撤销与审计

多租户系统上线后,平台运维迟早会遇到“客户说任务失败了,我们怎么排查”的问题。给平台人员一条“查看所有租户数据”的永久权限,确实方便,却把日常故障排查变成了长期越权入口;把支持人员临时写进客户管理员列表&…

2026/10/16 3:06:00 阅读更多 →
工业AI落地核心:感知-决策-执行闭环与物理世界耦合

工业AI落地核心:感知-决策-执行闭环与物理世界耦合

1. 工业AI不是“把算法搬进车间”,而是重新定义产线的呼吸节奏“他山之石可攻玉”这句老话,放在今天工厂里正被反复验证——但很多人没看清的是:那块“他山之石”,从来不是现成的通用大模型或云端API,而是一套在油污、…

2026/10/16 3:06:00 阅读更多 →
Windows环境下定时运行Python程序的方法总结

Windows环境下定时运行Python程序的方法总结

Windows环境下定时运行Python程序的方法总结本文记录如何在Windows环境(主机或服务器)下,通过批处理(.bat文件)定时运行简单的Python程序。一、前置条件(必须全部满足)二、run_waterview.bat 文…

2026/10/16 3:06:00 阅读更多 →
[SHOI2002] 舞会(洛谷-P6268)

[SHOI2002] 舞会(洛谷-P6268)

题目描述某学校要召开一个舞会。已知学校所有 n 名学生中,有些学生曾经互相跳过舞。当然跳过舞的学生一定是一个男生和一个女生。在这个舞会上,要求被邀请的学生中的任何一对男生和女生互相都不能跳过舞。求这个舞会最多能邀请多少个学生参加。输入格式输…

2026/10/16 3:06:00 阅读更多 →
Registry(注册表)设计模式

Registry(注册表)设计模式

没有Registry的写法 // ❌ 你自己手搓 CircuitBreakerConfig config CircuitBreakerConfig.custom()...build();CircuitBreaker payCb CircuitBreaker.of("payService", config); CircuitBreaker stockCb CircuitBreaker.of("stockService", config…

2026/10/16 3:06:00 阅读更多 →
2025年中国供应链物流科技创新发展报告

2025年中国供应链物流科技创新发展报告

适应人群为供应链物流企业(如快递、仓储、跨境物流)高管、物流科技从业者(AI 算法 / 自动化设备研发岗)、制造 / 电商企业供应链负责人、物流政策制定者及供应链物流研究人员。主要内容围绕 2025 年中国供应链物流科技创新展开,核心包括全球技术趋势(聚焦生成式 AI、供应…

2026/10/16 3:05:00 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →