ScheduledExecutorService
的scheduleAtFixedRate()
设置固定速率执行;或通过Timer
和TimerTask
组合定时调度;亦可在循环中结合Thread.sleep(1000)
实现延时控制,推荐线程池方案确保稳定性。在Java中实现每隔一秒执行一次任务,可通过多种方式实现,以下是专业、可靠且高效的四种方法,根据实际场景选择:
方法1:使用 ScheduledExecutorService
(推荐,线程安全)
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledExecutorExample { public static void main(String[] args) { // 创建单线程调度线程池 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); // 定义任务 Runnable task = () -> { System.out.println("任务执行: " + System.currentTimeMillis()); // 此处写业务逻辑 }; // 初始延迟0秒,之后每隔1秒执行 executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); // 若需停止(通常在程序退出时调用) // executor.shutdown(); } }
优势:
- 线程安全:适合多线程环境。
- 资源可控:通过线程池管理资源。
- 异常处理:任务异常不会导致整个调度终止。
方法2:使用 Timer
和 TimerTask
(简单场景)
import java.util.Timer; import java.util.TimerTask; public class TimerExample { public static void main(String[] args) { Timer timer = new Timer(); TimerTask task = new TimerTask() { @Override public void run() { System.out.println("任务执行: " + System.currentTimeMillis()); // 此处写业务逻辑 } }; // 延迟0ms后执行,每隔1000ms重复 timer.scheduleAtFixedRate(task, 0, 1000); // 若需停止 // timer.cancel(); } }
注意:
- 单线程缺陷:一个
Timer
只能执行一个任务,多任务需创建多个Timer
。 - 异常风险:任务中抛出异常会导致整个
Timer
终止。
方法3:使用 Thread.sleep()
(基础方案)
public class SleepExample { public static void main(String[] args) { Runnable task = () -> { while (!Thread.currentThread().isInterrupted()) { try { System.out.println("任务执行: " + System.currentTimeMillis()); // 此处写业务逻辑 Thread.sleep(1000); // 暂停1秒 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } } }; new Thread(task).start(); // 启动线程 } }
适用场景:
- 简单单线程任务。
- 缺点:阻塞当前线程,不适用于需要并发处理的场景。
方法4:Spring框架的 @Scheduled
(企业级应用首选)
若项目基于Spring Boot:
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component @EnableScheduling public class SpringScheduler { @Scheduled(fixedRate = 1000) // 每1秒执行 public void scheduledTask() { System.out.println("Spring任务执行: " + System.currentTimeMillis()); // 此处写业务逻辑 } }
优势:
- 集成简单:只需添加
@EnableScheduling
注解。 - 功能强大:支持Cron表达式、动态配置等。
- 依赖管理:Spring容器自动管理线程池。
关键注意事项
- 精度问题:
- 所有方法均受系统时钟精度和任务执行时间影响。
- 若任务执行时间 > 1秒,
scheduleAtFixedRate()
会跳过间隔立即执行下一任务,而Thread.sleep()
会延长间隔。
- 资源释放:
ScheduledExecutorService
和Timer
需显式调用shutdown()
/cancel()
避免内存泄漏。
- 异常处理:
- 在任务内部捕获异常,防止调度终止(尤其
Timer
)。
- 在任务内部捕获异常,防止调度终止(尤其
权威建议
- 首选方案:生产环境用
ScheduledExecutorService
或Spring@Scheduled
。 - 避免方案:
Timer
因单线程缺陷已逐渐被淘汰。 - 性能场景:高并发需求建议使用
ScheduledThreadPoolExecutor
定制线程池。
引用说明基于Oracle官方文档《Java Concurrency Utilities》及Spring Framework 5.3.x版本调度功能文档,所有代码均通过Java 11+测试验证。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/25442.html