当且仅当任务排队时,Java计时器才能阻止关闭

时间:2013-09-09 23:51:35

标签: java timer

我有一个java.util.Timer用于限制电子邮件发送(如果状态电子邮件已经发送到最近,那么现在不发送一个,而是创建一个计时器任务,以便稍后发送任何新的状态)。

我想要确保最终发送任何排队的电子邮件,但如果没有排队,则程序可以正常关闭。不幸的是,我无法决定如何解决这个问题:

  • 如果我将Timer置于默认(非守护进程)模式,那么它将使进程退出,直到它被明确取消。

  • 如果我将Timer设置为守护进程模式,那么它将允许关闭,但任何排队的任务(即未发送的电子邮件)都将被放弃。

到目前为止,我所做的是在发送电子邮件后明确取消定时器(并让它被垃圾收集),然后在需要时重新创建一个新的定时器以用于将来延迟的电子邮件。这似乎是不必要的流失。

有没有办法控制Timer的守护进程状态?或者是计时器的替代方案,可以实现这种延迟的电子邮件方案?

编辑请注意,我当前的解决方案,无论多么狡猾,都具有电子邮件发送“火上浇油”的优势。一旦对电子邮件发件人进行了调用,Timer的非守护进程状态将确保即使应用程序的某些其他部分同时关闭也会发送电子邮件。这样就不需要特殊的应用程序关闭代码来控制Timer。

4 个答案:

答案 0 :(得分:1)

如果@tieTYT建议的线程池执行程序不能满足您的需求,为什么不在应用程序退出时使用非守护程序计时器关闭计时器呢?假设您正在彻底关闭,您的代码应提供一种方法来执行清理步骤。或者作为最后的努力,你可以添加一个关闭钩子来取消计时器。

答案 1 :(得分:0)

javadoc of Timer说:

  

Java 5.0引入了java.util.concurrent包,其中一个并发实用程序是ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是Timer / TimerTask组合的更通用替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化TimerTask(只需实现Runnable)。使用一个线程配置ScheduledThreadPoolExecutor使其等同于Timer。

所以也许您应该使用ScheduledThreadPoolExecutor,然后使用Thread.join()

来阻止关机

答案 2 :(得分:0)

我没有尝试过,所以它可能有点愚蠢,但你能不能将你的计时器设置为非守护进程并注册一个关闭钩子,在取消计时器之前等待邮件队列为空?

答案 3 :(得分:0)

我看到了三种可能的方法来解决这个问题。根据你的情况,他们中的任何一个看起来都微不足道。

  1. 在应用程序结束时放置一些关机代码,等待发送电子邮件。你可以用普通线程做到这一点,或者 - 更优雅 - 使用Threadpool。
  2. 您将Thread配置为Deamon,它可以有效地保持JVM的运行,直到发送电子邮件。
  3. 您将工作委托给另一个进程,如ApplicationServer。这必须是一个管理的实例,确保运行。然后,您可以向其发送一个bean,等待并发送电子邮件。
  4. 哪一个是您的首选方式?