Java中Timer.cancel()后复用报错,求更优防抖实现方案
问题解答
Timer对象是否无法复用?
是的,Timer对象一旦调用cancel()方法后就无法复用。cancel()会终止Timer内部的调度线程,同时将Timer标记为已取消状态,后续再调用schedule()时,就会触发IllegalStateException提示"Timer already cancelled."。所以你的代码里如果不重新创建Timer实例,必然会报错。
不使用Timer实现防抖的更优方案
推荐两种更可靠的实现方式:
1. 使用ScheduledExecutorService(Java标准库)
ScheduledExecutorService是Java并发包提供的调度器,相比Timer优势明显:支持多线程调度、单个任务异常不会影响其他任务、API更灵活。适配你场景的代码示例如下:
private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture<?> debounceFuture; synchronized void debounceRequest() { // 取消之前待执行的任务 if (debounceFuture != null && !debounceFuture.isCancelled() && !debounceFuture.isDone()) { debounceFuture.cancel(false); } // 调度新任务,延迟150ms执行 debounceFuture = scheduler.schedule(() -> doSendRequest(), 150, TimeUnit.MILLISECONDS); } // 注意:程序关闭时需关闭调度器释放资源 // scheduler.shutdown();
2. 使用Guava的Debouncer(第三方库)
如果项目已引入Guava库,可直接用它封装好的防抖工具类,代码更简洁:
private final Debouncer<Void> debouncer = Debouncer.newDebouncer(150, TimeUnit.MILLISECONDS, Executors.newSingleThreadExecutor()); void debounceRequest() { debouncer.submit(() -> { doSendRequest(); return null; }); }
方案对比
ScheduledExecutorService属于Java标准库,无需额外依赖,适合对依赖有严格限制的项目。- Guava的
Debouncer封装更完善,代码更简洁,适合已引入Guava的项目。
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

