java Timer的缺点

为什么不推荐使用Timer?

 

一、timer的缺点

1.Timer对并发不友好

运行结果:

在一个Timer对象中,所有任务都由同一个线程来调度。如果有多个延时任务并且执行时间一致,Timer将一一执行任务,而不是并发执行。

如果同时存在很多延时任务,不能并发执行就成了Timer的硬伤。

2.如果强行并发,会有很多问题

上面提到,单个Timer对象是不支持并发的。所以,如果想要并发执行timeTask,就需要创建多个Timer对象。

运行结果:

创建多个Timer对象确实可以实现并发效果,但是问题来了:每一个任务都需要一个单独的Timer对象,每个Timer对象都需要开启一条线程。如果任务很多,就会遇到传统线程创建时的问题。

(1)所有创建过程都需要手工实现

(2)大量的Timer对象

(3)不能无限制地创建线程

3.如果某一任务执行时间过长,将影响其他任务的执行

Timer对调度的支持是基于绝对时间的,而不是相对时间。所以它对系统时间的改变非常敏感。

运行结果:

在同一Timer对象的情况下,如果一个任务执行时间过长,后面的所有任务都需要等待,这就导致延时任务失去了意义。

4.Timer线程不能捕获异常

Timer线程不能捕获异常。如果TimerTask抛出了RuntimeException异常(限于RuntimeException),会导致Timer线程终止。

运行结果:

在同一Timer对象的情况下,如果一个任务报出未捕获的异常,那么整个Timer对象将被取消,后面的所有任务都无法执行。

如果想在任务中抛出非RuntimeException的异常(在线程中抛出非RuntimeException的异常),需要强制加上try catch自行处理,否则程序无法通过编译。

5.TimeTask无法返回结果

现在我想执行一个延时任务,在任务中进行一个计算,最后得到任务执行的结果。(似乎没有什么必要在延时任务中进行计算,这里强行制造这样一个需求)

问题是,延时任务类需要继承TimerTask类并且实现run方法,而run方法是没有返回值的,不能用之前的Future去获取任务执行的结果。

如果要实现这样的场景,只能使用共享变量/get方法去获取延时任务中某个变量值。这种做法在前面也被提到过,存在很大的问题。

我个人认为这也是Timer的一个的缺陷。

二、总结

尽量不要使用Timer,使用ScheduledThreadPoolExecutor是更好的选择。

发表评论

电子邮件地址不会被公开。 必填项已用*标注