应在线程创建时通过 threadfactory 的 newthread 方法统一配置名称、优先级、异常处理器和守护状态:名称需含业务前缀与原子计数后缀;优先级默认设为 norm_priority(5);必须设置 uncaughtexceptionhandler 并记录关键上下文;业务线程非守护,后台线程可设为守护。

直接在创建线程时设置名称前缀、优先级和未捕获异常处理器,而不是依赖默认工厂或事后修改。关键在于实现 ThreadFactory 接口的 newThread 方法,在线程实例化那一刻就完成全部配置。
命名要带业务上下文,且必须在创建时设好
默认线程名如 pool-1-thread-1 完全无法区分业务来源。真正有用的名称应体现模块、功能和序号,例如 payment-notify-worker-1 或 mq-retry-consumer-2。
- 使用固定前缀 + 原子计数器(如
AtomicInteger)生成唯一后缀,避免重复 - 名称中禁用空格、斜杠、控制字符,防止 Arthas 等工具解析失败
- 不要在
Runnable.run()中调用Thread.setName()—— 线程池复用线程,名字不会刷新,监控看到的仍是初始名 - 不推荐用
Random生成后缀,无意义且有轻微性能开销
优先级通常设为 NORM_PRIORITY,慎调高低
Java 线程优先级范围是 1–10,NORM_PRIORITY = 5 是推荐值。高优先级不保证抢占成功,仅影响调度概率;生产环境随意调高可能引发饥饿或干扰 JVM 内部线程(如 GC 线程)。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 显式调用
t.setPriority(Thread.NORM_PRIORITY),避免继承父线程意外值 - 除非有强实时性要求(如金融风控低延迟路径),否则不建议偏离默认值
- 不同 OS 对优先级的支持程度不同,跨平台一致性差,不宜作为核心调度逻辑
未捕获异常必须由线程自己处理,不能靠外部兜底
线程内抛出未捕获异常会导致线程静默终止,任务丢失且无日志。默认行为只是打印到 System.err,线上基本不可见。
- 通过
t.setUncaughtExceptionHandler()绑定处理器,把异常写入日志文件、上报监控系统或触发告警 - 处理器里避免阻塞操作(如远程调用、大对象序列化),防止拖慢线程销毁流程
- 不要只打印堆栈,至少带上线程名、时间戳、业务上下文标识(如 traceId)
- 注意:该处理器只捕获
run()内未 try-catch 的异常,不处理Future.get()抛出的 ExecutionException
守护状态需按业务显式指定
是否设为守护线程(setDaemon(true/false))决定 JVM 退出时该线程是否被强制终止。线程池本身不自动管理这个属性。
- 业务型工作线程(如订单处理、消息消费)应设为非守护(
false),确保主线程退出前能完成清理 - 纯后台支撑类线程(如指标采集、心跳发送)可设为守护,避免阻塞 JVM 关闭
- 不显式设置会继承当前线程的 daemon 状态,容易因启动上下文不同导致行为不一致










