java.util.Timer:它被废弃了吗?

18

我在这个答案的评论以及许多其他关于调度的问题(抱歉,没有参考资料)中读到 java.util.Timer 已经被弃用。我真的希望不是这样,因为我正在使用它作为Java中轻量级的定时器(而且它工作得很好)。但如果它已被弃用,那我就要找别的解决方案了。 然而,快速查看1.6版本的API文档并没有提到它已经被弃用。 它甚至没有出现在 Sun 的Deprecated List 中。

它是否被正式弃用了*?如果是,我应该使用什么替代品?


* 另一方面,如果它没有被弃用, 人们能否停止诋毁这个无辜而精妙实现的类集合?


1
java.util.Timer的编写远非出色。它缺乏灵活性,难以编写可测试的代码。ScheduledExecutorService在各个方面都更好。 - skaffman
@skaffman,这可能是正确的。我唯一的问题是ScheduledExecutorService是否像Timer一样轻量级。它只是在Object.wait(long)上包了一个薄薄的包装...那么Scheduled...呢? - Dan Rosenstark
1
源代码在那里,你可以自己看一下。我能说的是,java.util.concurrent 相关内容(包括 ScheduledExecutorService)被设计用于极高的吞吐量,而 Timer 从未达到过这个水平。 - skaffman
谢谢@skaffman,我会查看源代码。 - Dan Rosenstark
6个回答

17

正如其他人提到的,它并没有被弃用,但我个人总是使用ScheduledExecutorService,因为它提供了更丰富的API和更大的灵活性:

  • ScheduledExecutorService允许您指定线程数量,而Timer始终仅使用单个线程。
  • ScheduledExecutorService可以使用ThreadFactory构建,从而允许控制线程方面的其他方面(例如优先级、ThreadGroupUncaughtExceptionHandler),而不仅仅是名称/守护进程状态。
  • ScheduledExecutorService允许以固定延迟和固定速率计划任务。
  • ScheduledExecutorService接受 Callable / Runnable 作为工作单元,这意味着您无需专门子类化 TimerTask 即可使用它;也就是说,您可以将相同的 Callable 实现提交给常规的 ExecutorService ScheduledExecutorService

最后一个好处可能对我很有吸引力。但除此之外,我担心ScheduledEx...可能会更“沉重”。你有什么想法? - Dan Rosenstark
3
假设你使用单线程创建了一个ScheduledExecutorService,尽管Timer包含其自己的优先级队列实现,但很可能不会看到任何性能差异。 - Adamski

8
我认为这是一个误解。 Timer类的JavaDoc提到了ScheduledThreadPoolExecutor,并指出这个类实际上是Timer/TimerTask组合的更加灵活的替代品。没有其他的意思。Timer没有被弃用。
JavaDoc中的另一个引用,这次是ScheduledThreadPoolExecutor:
ThreadPoolExecutor可以在给定延迟后额外安排命令运行,或定期执行。当需要多个工作线程时,或需要ThreadPoolExecutor的其他灵活性或功能时,此类优于Timer。

谢谢。那么你认为,在实现的重量方面——速度、内存使用、CPU使用——计时器是最轻量级的选择吗? - Dan Rosenstark
计时器在“轻量级”方面表现出色,因为它只有一个后台线程。请注意,Timer和ScheduledExecutorService都在内部使用数组来保存计划任务。因此,安排10,000,000个任务然后取消它们将使数组大小保持在10,000,000。实际上,这很少会成为问题。 - Adamski
说实话,在大多数情况下,我不知道也不关心性能问题。如果我遇到了性能问题,那么用ScheduledThreadPoolExecuter替换Timer.sleep()将是我最后考虑的事情之一... - Andreas Dolk
抱歉 @Andreas_D,我通常也不关心性能,但我正在成功地使用计时器创建MIDI音符循环器。因此,如果每秒可能有1K个预定任务...另一方面,也许我使用计时器是绝对疯狂的方向。 - Dan Rosenstark

6

不是所有情况都需要使用Timer。对于更复杂的定时器需求,您可能需要使用其他机制,例如Quartz,但Timer功能完美,并且将继续存在。


谢谢您的建议。我也会查看石英(Quartz)。 - Dan Rosenstark
是的,Quartz非常出色,尽管其API并不是很好。然而,Spring提供的Quartz包装器使其更加易用/灵活。 - Adamski

4

不,它没有被弃用。除了 Sun 的 弃用列表,你还会在已被弃用的类的 JavaDoc 中看到一个注释。例如,StringBufferInputStream 的注释如下:

已弃用。该类无法正确地将字符转换为字节。从 JDK 1.1 开始,创建字符串流的首选方式是使用 StringReader 类。


谢谢Bill,过时列表已经在问题中提到了。我想知道是否有一些内部消息让人们知道Timer已经过时了(或者其他的原因)。 - Dan Rosenstark
1
@yar:哦,是的,我没有注意到“这里”一词是链接的。Timer类本身的JavaDoc将有一条注释,让您知道是否已被弃用。 - Bill the Lizard
谢谢Bill,我承认将单词 here 链接不是锚文本的最佳实践 :) - Dan Rosenstark
@yar:我也有同样的问题,所以我不能太抱怨了。 :) - Bill the Lizard
我们都曾经历过那种场景。 - Dan Rosenstark

4
在JDK的Bug跟踪器中,有[JDK-8154799] 废弃计时器和定时任务。在2016年中期,JEP 277指出java.util.Timer(以及TimerTask)将被废弃于JDK 9。

几个Java SE API上将被添加、更新或移除@Deprecated注释。以下是一些示例。

[…]

  • java.util.TimerTimerTask 上添加 @Deprecated
然而,在JDK 9发布中,这些类并没有被废弃(废弃的类可以在 Deprecated List中找到)。

谢谢。读者应该在这里查看先前接受的答案:https://dev59.com/pXE95IYBdhLWcg3wp_un#2213146 - Dan Rosenstark
@Martin:截至今天(2017年6月26日),我没有看到任何关于Timer或TimerTask被弃用的参考资料。也许它们已经从列表中删除了。 - FractalBob
@FractalBob 确实这些类在JDK9 Deprecated List中没有出现。我找到了这个错误报告,看起来它们还没有决定是否会被弃用(请参见2016-10-04 21:40下的更改,位于Activity→All下)。 - Martin

2
在jdk1.6_10中,它并没有被弃用,因此不需要替代方案。

4
java.util.Date并没有被废弃,但它确实需要一种替代方案。请注意,本回答仅为翻译,不包含其他内容。 - skaffman
同样适用于观察者 / 可观察对象。 - Adamski
@skaffman,你用什么代替java.util.Date?如果它们不废弃这些东西,我怎么知道不要使用它们? - Dan Rosenstark
4
当你意识到某物是垃圾时,就要避免使用它。运用自己的判断力。java.util.Date 的事实替代品是 JodaTime。 - skaffman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接