2

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

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

  • 如果我将 Timer 保留在默认(非守护程序)模式,那么它将阻止进程退出,直到它被明确取消。

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

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

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

编辑请注意,我当前的解决方案,无论多么令人讨厌,都具有电子邮件发送是“一劳永逸”的优势。一旦对电子邮件发件人进行了调用,计时器的非守护程序状态确保电子邮件将被发送,即使应用程序的某些其他部分同时导致关闭。这避免了需要特殊的应用程序关闭代码来控制定时器。

4

4 回答 4

1

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

于 2013-09-10T00:48:18.940 回答
0

Timer的javadoc说:

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

因此,也许您应该改用 ScheduledThreadPoolExecutor,然后您可以使用Thread.join()来防止关闭

于 2013-09-09T23:57:40.330 回答
0

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

于 2013-09-10T07:39:17.533 回答
0

我看到了三种可能的方法来处理这个问题。从你的情况来看,它们都不是微不足道的。

  1. 在您的应用程序末尾放置一些关闭代码以等待电子邮件发送出去。您可以使用普通线程执行此操作,或者更优雅地使用 Threadpool。
  2. 您将 Thread 配置为 Deamon,它可以有效地保持 JVM 运行,直到发送电子邮件。
  3. 您将工作委托给另一个进程,例如 ApplicationServer。这必须是一个受管理的实例,确保正在运行。然后,您可以向它发送一个 bean,等待并发送电子邮件。

哪一种是您的首选方式?

于 2013-09-11T05:31:52.233 回答