Java如何创建后台运行的定时器 同时不阻塞用户正常交互操作
Java 非阻塞后台定时更新股价实现方案
核心实现逻辑
使用Java标准库自带的ScheduledExecutorService实现定时任务,该工具会在独立的后台线程池运行调度任务,和处理用户交互的主线程完全隔离,不会阻塞用户操作,也不需要手动编写sleep逻辑处理间隔。
可直接运行的示例代码
import java.util.Random; import java.util.Scanner; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class StockGame { // 用volatile修饰保证多线程访问的可见性,后台更新后主线程能立刻读到最新价格 private static volatile double stockPrice = 100.0; // 随机数生成器,用来模拟股价波动 private static final Random random = new Random(); public static void main(String[] args) { // 初始化单线程的定时调度器,足够应对小型课程项目需求 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); // 提交定时任务:初始0延迟后开始执行,每隔10秒执行一次股价更新 executor.scheduleAtFixedRate(() -> { // 模拟股价在±5%范围内随机波动,你可以替换成自己的股价更新逻辑 double changeRate = 0.95 + random.nextDouble() * 0.1; stockPrice = Math.round(stockPrice * changeRate * 100) / 100.0; // 测试用,可以删掉这行打印 System.out.printf("\n[系统通知] 股价已更新,当前价格:%.2f\n", stockPrice); }, 0, 10, TimeUnit.SECONDS); // 主线程处理用户输入,完全不受后台定时任务影响 Scanner scanner = new Scanner(System.in); while (true) { System.out.print("\n请输入操作(1查看股价,2退出):"); int op = scanner.nextInt(); if (op == 1) { System.out.printf("当前股价:%.2f\n", stockPrice); } else if (op == 2) { // 退出前关闭调度器,释放线程资源 executor.shutdown(); System.out.println("程序退出"); break; } else { System.out.println("无效操作,请重新输入"); } } scanner.close(); } }
上面的代码可以直接在repl.it上运行,后台每10秒自动更新股价,主线程随时可以响应用户输入,不会出现阻塞。
注意事项
- 跨线程共享的股价变量必须加
volatile修饰,避免后台线程更新后主线程读取到旧值的可见性问题 - 如果后续需要实现暂停更新、调整更新间隔的需求,可以接收
scheduleAtFixedRate方法返回的ScheduledFuture对象,调用cancel()方法取消现有任务后重新提交新的调度任务即可 - 课程项目场景下单线程调度器足够使用,如果后续需要扩展多支股票的并行更新,可以换成
Executors.newScheduledThreadPool(n)指定线程池大小,n为需要并行处理的股票数量
学习资源
直接查阅JDK官方文档中java.util.concurrent.ScheduledExecutorService相关章节即可,标准库文档包含完整的方法说明和使用示例,足够掌握该工具的所有常用用法。
内容的提问来源于stack exchange,提问作者Jared
相关产品推荐
相关产品推荐

