在Java里如何编写控制台任务调度示例_Java流程设计项目说明
发布时间 - 2026-02-02 00:00:00 点击率:次ScheduledExecutorService 是替代 Timer 的健壮选择,支持线程安全、拒绝策略与异常可见性;应避免 sleep 循环,用 scheduleAtFixedRate 或 scheduleWithFixedDelay 配合 ScheduledFuture 控制生命周期,通过 AtomicBoolean 协同用户输入退出,并统一日志同步以避免竞态。
用 ScheduledExecutorService 启动周期性控制台任务
Java 标准库不推荐用老旧的 Timer,ScheduledExecutorService 是更健壮的选择。它线程安全、支持拒绝策略、能复用线程池,且异常不会静默终止调度。
常见错误是直接 new Thread + sleep 循环——这无法优雅关闭、不处理异常、也不可控暂停/恢复。
- 用
Executors.newScheduledThreadPool(1)创建单线程调度器(多任务需权衡并发数) - 调用
scheduleAtFixedRate()适合固定间隔执行(如每 5 秒打印一次),注意初始延迟设为 0 或正数 - 若任务执行时间可能超过周期(比如耗时 6 秒但设了 5 秒周期),
scheduleAtFixedRate会“追赶”,而scheduleWithFixedDelay则等上一次结束后再延时启动 - 务必保留对
ScheduledFuture的引用,以便后续cancel(true)
如何让控制台任务响应用户输入并安全退出
控制台程序常需按某个键(如 "q")停止调度,但 System.in.read() 是阻塞的,不能和调度器共用一个线程。
典型陷阱是把 Scanner 放在调度任务里轮询输入——这既浪费 CPU,又因输入缓冲行为导致漏读或卡死。
- 开一个独立线程监听
System.in,用System.in.available() > 0配合非阻塞检查(注意:Windows 控制台需回车才触发可用字节) - 更可靠的做法是用
Scanner在主线程阻塞读取,同时用AtomicBoolean running = new AtomicBoolean(true)作为共享状态 - 调度任务开头加
if (!running.get()) return;,主线程收到退出指令后设running.set(false)并调用scheduler.shutdownNow() - 别忘了
shutdownNow()返回未执行的Runnable列表,可用来做清理日志
避免 System.out.println 在调度中引发乱序或丢失
多个线程(调度线程 + 输入监听线程 + 主线程)同时写控制台,可能输出错行、字符截断,甚至部分日志完全不显示。
这不是 bug,而是 PrintStream 虽线程安全,但每次 println 是“获取锁 → 写内容 → 换行”三步,中间可能被其他线程插入。
- 所有日志统一走
System.out.printf("[%s] %s%n", Thread.currentThread().getName(), msg),便于排查来源 - 若需强一致性(比如关键状态快照),用
synchronized (System.out) { System.out.println(...); } - 生产级建议替换为
java.util.logging.Logger或slf4j,它们默认同步且支持异步 Appender - 避免在调度任务里拼接
长字符串再打印——先格式化好再输出,减少锁持有时间
调试时怎么看任务是否真在运行、有没有堆积
控制台看不到线程池内部状态,仅靠打印 “task executed” 容易误判:可能任务已提交但线程池满、或异常抛出后被吞掉。
最常忽略的是未捕获异常——ScheduledExecutorService 默认不打印堆栈,任务一崩就静默停摆。
- 给调度器传入自定义
ThreadFactory,为线程命名(如"scheduler-pool-%d"),方便 jstack 查看 - 包装任务:用
try-catch(Throwable t)包住整个Runnable体,并打印t.printStackTrace()到System.err - 通过
scheduler.awaitTermination(1, TimeUnit.SECONDS)测试 shutdown 是否真正结束(返回 false 表示还有活跃任务) - 临时加一行
System.out.println("Pool size: " + ((ScheduledThreadPoolExecutor)scheduler).getActiveCount());看当前忙线程数
# java
# js
# windows
# app
# 字节
# 栈
# ai
# win
# stream
# 标准库
# if
# try
# catch
# Logging
# printf
# 字符串
# 循环
# 堆
# 线程
# 线程生命周期
# 主线程
# Thread
# 并发
# 异步
# bug
# 的是
# 看着
# 也不
# 见性
# 放在
# 多个
# 设为
# 执行时间
# 这不是
# 会让
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何正确选择百度移动适配建站域名?
Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】
图册素材网站设计制作软件,图册的导出方式有几种?
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
javascript中的try catch异常捕获机制用法分析
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
如何在Windows 2008云服务器安全搭建网站?
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
北京专业网站制作设计师招聘,北京白云观官方网站?
昵图网官网入口 昵图网素材平台官方入口
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
JavaScript常见的五种数组去重的方式
手机软键盘弹出时影响布局的解决方法
深入理解Android中的xmlns:tools属性
如何彻底卸载建站之星软件?
再谈Python中的字符串与字符编码(推荐)
个人网站制作流程图片大全,个人网站如何注销?
微信小程序 require机制详解及实例代码
如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程
Laravel如何优化应用性能?(缓存和优化命令)
Laravel如何实现多对多模型关联?(Eloquent教程)
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
如何解决hover在ie6中的兼容性问题
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
香港网站服务器数量如何影响SEO优化效果?
使用Dockerfile构建java web环境
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
Laravel用户密码怎么加密_Laravel Hash门面使用教程
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
Laravel集合Collection怎么用_Laravel集合常用函数详解
敲碗10年!Mac系列传将迎来「触控与联网」双革新
高防服务器如何保障网站安全无虞?
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
音响网站制作视频教程,隆霸音响官方网站?
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
详解CentOS6.5 安装 MySQL5.1.71的方法
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
Python结构化数据采集_字段抽取解析【教程】
php 三元运算符实例详细介绍
如何用免费手机建站系统零基础打造专业网站?
深圳网站制作培训,深圳哪些招聘网站比较好?
Laravel怎么多语言本地化设置_Laravel语言包翻译与Locale动态切换【手册】
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】


