线程池详解:ThreadPoolExecutor参数配置、拒绝策略与线上避坑实践
聊到线程池的使用实践很多人第一反应是 new 一个 ThreadPoolExecutor然后往里面 submit 任务。真不是故意泼冷水这个操作看起来简单但线上环境里线程池用不好带来的问题一点不输内存泄漏。我先后在几家公司维护过交易、异步任务、消息推送这类系统反复遇到过任务堆积、OOM、线程耗尽、接口被拖垮的情况很多最后都定位到了线程池配置不合理。所以这篇内容不打算讲太深的理论而是把我在实践中踩过坑、验证过可行的做法整理出来给正在用或者打算用线程池的开发者一个参考。1. 线程池是什么为什么我劝你别自己 new Thread()很多代码里有这样的场景收到一个请求后台需要同步一批数据于是new Thread(() - doSomething()).start()。小流量没事一旦请求量上来每个请求都创建线程系统很快就会出现线程数量飙升、内存上涨、切换开销暴涨。我见过一个数据同步的服务高峰期每秒几十个请求每个请求都开三五个线程跑几个小时以后线程数直接到几千CPU 大部分时间花在上下文切换上真正的业务计算反而慢下来。1.1 每次 new Thread 到底贵在哪里创建线程贵不只是 Java 层面 new 一个对象更关键的是它要跟操作系统打交道。每个线程都要分配独立的调用栈JVM 默认栈大小 1MB64 位 Linux 上很多环境是 1MB1000 个线程光栈内存就是 1GB这还只是静态占用。同时线程创建会触发系统调用、内核线程的创建、线程调度器的注册第一次运行还要经历 CPU 缓存冷启动。对比来看从线程池里取一个已经活着、已经完成缓存的线程去执行任务成本便宜很多。从响应时间的角度也值得注意。一个任务的执行时间如果是 50ms其中线程创建可能就要花 13ms。看起来不多但如果任务本身只有 10ms线程创建的开销占比就到了 30%这就非常不划算了。所以在线程频繁创建销毁的场景里池化的收益非常明显。1.2 线程池解决的三个核心问题如果我们用池化思路本质上是在解决三件事。第一资源复用。一组线程反复干活省掉频繁创建销毁的开销降低线程栈内存和内核对象数量。第二限制并发。线程池可以约束同时执行的任务数量防止无限制创建线程把 CPU、内存、数据库连接等资源耗尽。没有上限的并发在极端流量下往往比没有队列更容易出事。第三任务缓冲。当瞬间任务超过线程处理能力时任务可以先进队列而不是直接丢弃这给系统争取了平滑处理流量的机会。配合拒绝策略可以在“处理不过来的情况”下做出明确选择。理解了这三点后面配置参数时就不会总问“为什么要有最大线程数”“为什么要队列”了。线程池本质上是给异步任务一个可管理的资源池而不是简单的“多线程执行器”。另外也要说一句线程池不是所有异步场景的最优解。如果任务量很小、频率很低比如每天凌晨跑一次、任务量只有几十个直接用简单并发甚至串行也完全没问题不必为了用线程池而用。引入线程池的同时也引入了队列、拒绝策略、生命周期管理等复杂度小场景下这些复杂度不划算。2. ThreadPoolExecutor 七个参数别再看一遍又忘2.1 corePoolSize、maximumPoolSize 和 keepAliveTimeThreadPoolExecutor 构造方法里最核心的三个数字corePoolSize、maximumPoolSize、keepAliveTime。先明确执行流程新任务提交时如果当前线程数小于 corePoolSize直接新建线程执行达到 corePoolSize 后新任务优先进 workQueue如果队列满了并且线程数还没有到 maximumPoolSize再继续创建线程直到 maximumPoolSize当线程数已经到了 maximumPoolSize 且队列也满了就走拒绝策略。这个流程很多文章画过图但我更想强调一点队列在中间起到的是缓冲作用它让线程数在 core 和 max 之间的增长不是一上来就无脑扩张而是先让任务排队等到队列也扛不住才开始扩到 max。keepAliveTime 控制的是超过 corePoolSize 的线程空闲多久后回收。比如 core8、max16任务高峰过去后超过 8 的部分如果空闲满 30 秒就会被回收回到常驻 8 个线程的状态。allowCoreThreadTimeOut(true) 可以连核心线程也一起回收但日常业务中我不建议随便开核心线程频繁销毁重建反而会影响响应速度。2.2 workQueue 选型有界、无界还是同步传递队列的选择直接影响线程池行为。LinkedBlockingQueue 如果使用无参构造容量是 Integer.MAX_VALUE任务可以无限堆积线程数永远不会涨到 core 之上除非 core 满后队列堆到 OOM。很多人踩过这个坑用了 Executors.newFixedThreadPool以为能控制最大线程数其实线程数永远不变任务全在无界队列里排队一旦流量突增内存直接爆掉。ArrayBlockingQueue 是有界队列必须指定容量它能让系统在任务过多时触发拒绝策略而不是默默堆积。SynchronousQueue 不是一个真正意义上的存储队列它不存任务提交任务时必须有一个空闲线程立刻接手否则就阻塞或触发拒绝Executors.newCachedThreadPool 用的就是它所以线程数可以无限膨胀。实际业务中我一般优先选择有界队列容量根据系统可接受的最大排队时间来定。比如一个任务平均执行 200ms队列容量 500那么最坏情况下最后一个任务的等待时间大概是 500 × 200ms 100 秒这显然太长就需要缩减队列或者提高处理能力。排队时间等于队列容量乘以平均任务耗时的估算方法可以作为容量设计的第一版依据。2.3 threadFactory 与拒绝策略最容易偷懒也最容易出事的两环默认线程工厂生产的线程名字是 pool-1-thread-1 这种格式线上日志一多根本看不出这个线程来自哪个业务排查问题只能靠猜。我习惯在创建线程池时强制要求自定义 ThreadFactory把线程名字统一成“业务名-池角色-序号”比如 order-async-pool-0。这样出现 CPU 飙升、线程数异常时jstack 一抓就能知道是哪个线程池出了问题。线程工厂里还可以设置异常处理器。比如某个任务抛出了未捕获异常默认情况下线程会被销毁然后重新创建异常信息可能只在后台打印不一定进得了业务日志系统。我们可以给线程设置 uncaughtExceptionHandler把异常统一记到日志里至少不会丢得无声无息。拒绝策略是最后一道防线。默认的 AbortPolicy 会在任务被拒绝时抛出 RejectedExecutionException但很多场景下这个异常会被业务吞掉导致任务静默丢失。CallerRunsPolicy 不丢任务而是让提交任务的线程自己执行相当于用调用方线程兜底同时提供一种自然的背压效果缺点是调用方可能会被慢任务拖住选择它时要评估调用链路的超时容忍度。DiscardPolicy 和 DiscardOldestPolicy 都是丢弃任务除非任务允许丢否则我基本不会用。3. 参数到底怎么定从公式到压测的一条完整路径3.1 别再让公式背锅网上流传很多线程数计算公式CPU 密集型用 CPU 核数 1IO 密集型用 2 × CPU 核数还有更精细的 N × (1 等待时间 / 计算时间)。这些公式不是不能用但它们只是“初始值”不是“标准答案”。有一次我把 IO 密集型服务的核心线程数设成 2 倍核数结果下游数据库连接池先被打满了线程池还有大量线程在等待获取连接性能反而更差。那一刻我才意识到线程数不是越大越好还要看下游资源能不能扛住。正确路径应该是先确定任务类型CPU 密集、IO 密集、混合型用公式算出一个初始范围然后压测观察 CPU 使用率、线程等待时间、队列积压、下游资源水位最后根据监控数据微调。比如请求型任务平均耗时 200ms其中真正的 CPU 计算只有 20ms剩下 180ms 都在等网络、数据库、外部服务。那这个任务等待时间占比 90%按公式算线程数大概可以到核数的 10 倍左右。但如果下游数据库连接池只有 50 个连接线程池开 200 个线程最终大部分线程会在获取数据库连接时阻塞。所以线程池的参数永远要放在整个资源链路里去看。3.2 一个完整可落地的线程池配置示例下面给一个我常用的线程池配置大家可以直接参考结构调整ThreadPoolExecutor exec new ThreadPoolExecutor( 8, // corePoolSize 16, // maximumPoolSize 30L, // keepAliveTime TimeUnit.SECONDS, new ArrayBlockingQueue(2000), // 有界队列容量看排队容忍度 new ThreadFactory() { private final AtomicInteger seq new AtomicInteger(0); Override public Thread newThread(Runnable r) { Thread t new Thread(r, biz-async-pool- seq.getAndIncrement()); t.setUncaughtExceptionHandler((thread, throwable) - logger.error(async task uncaught error, throwable)); return t; } }, new ThreadPoolExecutor.CallerRunsPolicy() ); exec.prestartAllCoreThreads();先看 core8、max16 这个数字如果服务部署在 8 核的机器上核心线程数设为 8 比较合理任务类型如果是 IO 密集那么可以允许峰值时线程数上涨到 16但不会无限涨。队列容量 2000加上最多 16 个正在执行的线程系统在不触发拒绝策略的情况下最多缓存 2016 个任务如果平均任务 200ms那这批任务最坏也需要 2016 × 200ms 403 秒才能全部处理完这就意味着队列容量 2000 对很多场景其实已经偏大了。所以容量一定要结合实际最大排队时长来调。CallerRunsPolicy 的选择要分场景。如果任务提交方是业务接口的请求线程采用这个策略后当线程池满时请求线程会自己去跑任务接口响应时间会明显增加但好处是任务不会丢。对于实时性要求不太高、可以接受偶发变慢的后台任务这种兜底方式很实用。对于异步通知这种不能丢失的任务可以在拒绝策略里把任务写入本地表或者消息队列等系统恢复后再补偿执行。3.3 动态调参线程池不是定死的很多开发者配置完线程池就不再动了但线上流量是有波动的。ThreadPoolExecutor 提供了 setCorePoolSize、setMaximumPoolSize、setKeepAliveTime 等动态调整方法我们可以结合监控数据在运行时调整。例如我习惯每隔一段时间采集一次队列积压量、activeCount、每秒完成任务数、拒绝次数。如果发现队列长期处于 80% 以上的水位说明当前处理能力不足可以适当调大 maximumPoolSize 或者缩小队列让更多任务直接进入处理阶段。如果发现 activeCount 长期低于 corePoolSize说明线程大部分时间闲着了可以缩小 corePoolSize减少常驻内存。动态调参要注意一点setMaximumPoolSize 如果设置得比当前线程数小线程池会先把多余线程逐步回收但不会主动中断正在运行的任务所以操作本身不会导致任务丢失。不过调整过频会带来不稳定建议通过配置中心下发参数而不是在代码里写死一个定时器频繁改。4. 实操中的坑这些问题我不止一次在线上碰到4.1 没 shutdown 的线程池程序退出时全卡住这个坑在很多独立开发的应用里尤其常见。线程池里的线程默认是非守护线程只要还有一个活着JVM 就不会退出。如果你在本地写一个 demo执行完 main 方法后程序迟迟不结束多半就是线程池没有关闭。在 Web 容器里也有类似情况服务停机时如果线程池不优雅关闭已有的异步任务可能会被直接打断正在写的数据可能只写了一半。正确的关闭姿势是把 shutdown 和等待结束配合起来。shutdown() 之后线程池不再接受新任务但已经在队列里的任务会继续执行shutdownNow() 会尝试中断正在执行的任务并返回还没执行的任务列表。一般流程是先调用 shutdown()然后 awaitTermination(超时时间)如果超时还没结束再调 shutdownNow()最后再 awaitTermination 一次。还有一点使用 Executors 创建的一些线程池如果不调用 shutdown进程不会退出但有些框架比如某些 Spring Boot 应用在容器关闭时不会自动帮你关闭自定义线程池需要自己通过生命周期回调处理。我踩过一次服务已经停了日志却还在打查了很久才发现是自定义线程池没有在停机钩子里关闭。4.2 队列堆满后任务到底被谁吃掉了之前一个同事排查一个问题现象是某个批处理任务处理结果不完整但日志里没有任何异常。翻代码发现他把拒绝策略设成了 DiscardPolicy任务被静默丢弃了。这种问题非常隐蔽因为你不知道是任务本身失败还是任务压根没执行。除了见队就丢更常见的是无界队列带来的任务堆积。无界队列不会触发拒绝策略看起来任务都“接受”了实际上内存持续增长直到 OOM然后整个服务被重启。这类堆问题不是线程池满了导致的但它很容易和线程池混在一起被误判。我的建议是凡是可能丢弃任务的策略都在自定义拒绝策略里把任务信息任务类型、参数摘要、拒绝原因、当时线程池状态记录到日志或者监控系统。比如重写 rejectedExecution 方法打一条 error 日志并把被拒绝的任务塞入一个持久化存储等待后续补偿。这样即使真的丢弃我们也知道丢了什么、为什么丢。4.3 异常被吞得干干净净排查到怀疑人生线程池里的异常处理是一个大坑而且分两种场景。第一种是用 execute 提交 Runnable任务内部抛出 RuntimeException线程池会捕获它并交给线程的 UncaughtExceptionHandler默认行为是打印堆栈但线程池本身不会停止。第二种是用 submit 提交任务异常会被封装进返回的 Future 里如果你从不调用 future.get()那异常永远不会出现在日志里但任务实际是失败的。我推荐两个手段并用来避免这个问题。第一任务内部必须自己捕获异常并按业务日志规范记下来不要把异常抛出到线程池层。第二重写 ThreadPoolExecutor 的 afterExecute 方法无论任务通过 execute 还是 submit 提交都能被监控到Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); if (t null r instanceof Future?) { try { ((Future?) r).get(); } catch (CancellationException ce) { t ce; } catch (ExecutionException ee) { t ee.getCause(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } if (t ! null) { logger.error(task execute error, t); } }这段代码的逻辑是如果已经传入了异常 t直接用如果没有就尝试从 Future 里把异常取出来。因为 submit 包装后的任务其异常不会直接传给 afterExecute 的 t 参数必须 get 才能拿到。这个写法不是万能的比如任务里调用了 future.get() 且自己处理了异常那么 afterExecute 不会再感知到但作为兜底已经很够用。另外一个关联坑是 ThreadLocal 的泄漏。线程池里的线程是复用的如果任务里往 ThreadLocal 写了值却不清理下一个任务复用同一个线程时会读到上一个任务残留的数据轻则出现脏数据重则把用户 A 的上下文串到用户 B 的请求里。尤其是日志链路追踪用的 MDC任务执行完一定要在 finally 里 remove。5. 线程池在真实业务里的落地姿势5.1 批量任务拆分、聚合与超时兜底业务里最常见的需求是把一个大的批量任务拆成若干子任务并发执行最后汇总结果。比如有 1000 个用户需要推送消息每次推 200 个可以降低耦合和失败爆炸半径于是拆成 5 批每批一个任务交给线程池执行。如果直接用 Future.get() 依次拿结果会有一个问题如果第一个任务耗时很长后面几个任务明明已经完成了主线程还是要等第一个任务完成才能继续白白损失并行度。更好的方案是用 ExecutorCompletionService 包装线程池它会先完成先返回主线程可以按完成顺序及时处理ExecutorCompletionServiceResult service new ExecutorCompletionService(exec); for (Task t : tasks) { service.submit(() - doTask(t)); } for (int i 0; i tasks.size(); i) { FutureResult future service.poll(5, TimeUnit.SECONDS); if (future null) { // 超时记录未完成任务继续等待或者放弃本次批量 continue; } // 异常在 future.get() 时统一处理 }使用 poll 超时而不是阻塞 take可以避免某一个子任务长时间不结束导致整个批量任务无限等待。对超时后仍未完成的任务应该记录下来走补偿或者告警。这个兜底现实里非常重要因为线程池中的任务再可靠也可能会因为外部依赖迟迟不返回而拖住批量流程。5.2 线程池隔离别让一个慢业务拖垮整个应用一个服务里如果所有异步任务共用一个线程池只要有一个业务的执行时间特别长就会占满整个线程池其他业务的请求只能排队等着。最典型的是某些定时任务调用了外部慢接口一个任务卡十几秒后面所有异步操作全部延迟。解决思路是隔离按业务的重要程度和风险程度划分多个线程池。核心链路用独立线程池并且有界队列较小、拒绝策略明确非核心的慢任务单独放一个池子线程数和队列容量可以相对宽松但不能影响核心池。更进一步如果不想为每个业务都维护一个 ThreadPoolExecutor可以引入信号量做并发控制或者用轻量级的线程池隔离方案。但我的经验是直接拆池子最简单也最好排查问题。每个池子的线程名带上业务前缀监控也能分开看。线上出问题时通过线程名和监控指标很快就能圈定是哪个链路出了问题。5.3 CompletableFuture 搭配自定义线程池的注意点CompletableFuture 很好用它让异步编排变得很直观。但有一个隐患如果不指定线程池supplyAsync 和 thenApplyAsync 会默认使用 ForkJoinPool.commonPool()。这个公共线程池的线程数是 CPU 核数减 1如果你在里面放了阻塞操作比如 HTTP 调用、数据库查询那么整个 JVM 中所有用到 common pool 的地方包括 parallelStream都会一起卡住。所以只要涉及真实业务就显式传入定义好的线程池而不是用默认池。另一个坑是 CompletableFuture 的异常处理。异步回调里的异常不会主动抛出必须显式调用 join()、get() 或者注册 exceptionally/whenComplete 才会捕获到。否则一段异步代码出错了外层根本感知不到问题会被拖到很晚才暴露。还有一个容易被忽略的问题异步回调链路可能跨池执行。比如 supplyAsync 在池 AthenApplyAsync 没有指定池就会在 ForkJoinPool.commonPool 里执行。这时候线程上下文、MDC、事务这些东西很容易出问题。建议整个链路的每一步都显式指定同一个自定义线程池或者干脆用 CompletableFuture 但只做最简单的编排别把线程池换来换去。6. 我的最终建议先把线程池当“资源”来管6.1 少用 Executors 快捷方法多数时候不是好选择Executors 提供的 newFixedThreadPool、newCachedThreadPool、newScheduledThreadPool 用起来确实方便但它们的行为很多不适合生产环境。newFixedThreadPool 的队列是无界的任务可以无限堆积最大线程数永远等于核心线程数线程数看起来是固定的实际系统却是靠堆内存去硬扛流量。newCachedThreadPool 最大线程数是 Integer.MAX_VALUE流量一旦异常线程数可以膨胀到把系统打挂。newScheduledThreadPool 用无界延迟队列同样有堆积风险。我不是说这些方法不能用而是在使用前必须清楚它们背后的资源模型。如果只是本地 demo、一次性脚本用 Executors 快捷方法无可厚非线上服务我建议一律用 ThreadPoolExecutor 显式声明参数哪怕只是多写几行也能逼自己想清楚每个配置。6.2 日志、监控与优雅停机要一起考虑最后再说一个整体建议线程池不是写完 submit 就结束的东西它应该被当作一个资源池来运维。线程池相关的指标至少要暴露这些当前线程数、活跃线程数、队列积压量、完成任务数、拒绝次数、线程池状态。有监控系统就把它们上报没有监控就写一个定时任务定期打印日志。我个人的习惯是在项目里封装一个简单的线程池管理组件统一创建、统一关闭、统一上报指标。这样既避免了每个业务各写一套线程池配置也方便在出问题时快速定位。最后再分享一个我经常问自己的问题如果线程池满了、任务堆积了、下游变慢了这个系统还能不能扛住想清楚这三问线程池的使用实践才算真的过关。

相关新闻

C# WebSocket工业级通信底座:原生API+TLS+Protobuf实战

C# WebSocket工业级通信底座:原生API+TLS+Protobuf实战

简介:本资源是一套完整的C# WebSocket双向通信实战Demo,面向.NET初学者与中级开发者,解决实时通信场景下客户端与服务端协同开发的学习难点。压缩包共76个文件,包含15个核心C#源码文件(如WebSocketClient.cs、WebSocke…

2026/10/11 2:05:48 阅读更多 →
K8s Ingress rewrite规则详解:正则捕获组为何总在404后才发现坑

K8s Ingress rewrite规则详解:正则捕获组为何总在404后才发现坑

前阵子处理一个线上小事故,现象很典型:一套后端服务挂在 K8s 集群里,通过 Ingress 对外提供 API,某天联调时发现所有带子路径的请求全部 404,但根路径和健康检查都正常。第一反应是 Service 配置错了,或者后…

2026/10/11 2:05:48 阅读更多 →
用Python从零实现IP扫描工具:主机探测与端口扫描实战

用Python从零实现IP扫描工具:主机探测与端口扫描实战

朋友们平时做网络调试、内网排查或者学习 TCP/IP 协议的时候,经常需要快速了解某个网段内有哪些主机在线、哪些端口是开放的。如果用现成的商业软件,要么收费,要么功能太重;如果手动一条条 ping 和 telnet,又太低效。其…

2026/10/11 2:05:48 阅读更多 →

最新新闻

手写递归下降语法分析器:从文法到AST的完整实现

手写递归下降语法分析器:从文法到AST的完整实现

简介:本资源是一份面向计算机专业本科生及编译原理初学者的语法分析实践教学材料,聚焦编译器核心环节——语法分析的原理理解与代码实现。内容覆盖上下文无关文法定义、LL/LR分析对比、递归下降解析器设计、抽象语法树构建及Yacc/Bison工具链基础应用&am…

2026/10/11 2:58:19 阅读更多 →
Blender渲染提速实战:Cycles/Eevee参数优化与云渲染交付

Blender渲染提速实战:Cycles/Eevee参数优化与云渲染交付

最近接了个临期交付的项目,镜头不多,可一测渲染,单帧1080P在Cycles里要跑12小时。客户催得紧,本地这台机器明显吃不消。我第一反应不是换电脑,而是把渲染设置从头到尾捋了一遍——采样、反弹次数、降噪、输出格式&…

2026/10/11 2:58:19 阅读更多 →
弹道目标状态估计的Matlab仿真:EKF与UKF对比与工程实践

弹道目标状态估计的Matlab仿真:EKF与UKF对比与工程实践

刚把手头的弹道目标状态估计仿真系统跑完,准备把整个设计过程、滤波算法、参数整定和踩过的坑都写下来。这套东西用 Matlab 实现,核心就是两个非线性滤波器:扩展卡尔曼滤波 EKF 和无迹卡尔曼滤波 UKF,作用对象是含空气阻力的弹道目…

2026/10/11 2:58:19 阅读更多 →
儿童友好战略:从品牌定位到门店运营的完整拆解

儿童友好战略:从品牌定位到门店运营的完整拆解

看到这个标题,你大概已经知道我说的是哪家快餐巨头。但我想聊的,不是它的汉堡和薯条,而是“孩子们可以尽情做孩子的地方”这句话背后的一整套商业操作系统。它让一个卖炸鸡汉堡的品牌,硬生生在餐饮红海里挤出一条别人很难短期复制…

2026/10/11 2:58:19 阅读更多 →
局域网自建AI Agent平台:Docker部署DeepSeek与Harness实战

局域网自建AI Agent平台:Docker部署DeepSeek与Harness实战

1. 为什么要在局域网里自建 AI Agent 平台1.1 从“调用云端 API”到“把模型搬进机房”的转变过去一年,我身边不少做企业内部工具的朋友都经历了同一个心路历程:一开始图省事,直接调云端大模型的 API,几行代码就能跑通一个问答机器…

2026/10/11 2:58:19 阅读更多 →
MySQL CRUD 核心实践:从增删改查到事务、索引与防注入

MySQL CRUD 核心实践:从增删改查到事务、索引与防注入

“MYSQL ---CURD”,看到这个标题我就绷不住了——兄弟,这个词八成是想写 CRUD(Create、Read、Update、Delete),也就是对数据库里数据的增、删、改、查。字母顺序调换一下,意思完全变了。不过话说回来&#…

2026/10/11 2:57:18 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →