在Java web app中运行常规后台事件

在Java web app中运行常规后台事件,java,events,Java,Events,在podcast#15中,Jeff提到他在twitter上讲述了如何在后台运行常规活动,就好像这是一个正常的功能一样——不幸的是,我似乎无法通过twitter找到这一点。现在,我需要做一件类似的事情,并将向大众提出这个问题 我目前的计划是,当第一个用户(可能是我)进入站点时,它会启动一个后台线程,等待分配的时间(每小时一次),然后启动阻止其他用户的事件(我是一名Windows程序员,所以我从事件和WaitOnMultipleObjects的角度考虑),直到完成 Jeff是如何在Asp.Net中做

在podcast#15中,Jeff提到他在twitter上讲述了如何在后台运行常规活动,就好像这是一个正常的功能一样——不幸的是,我似乎无法通过twitter找到这一点。现在,我需要做一件类似的事情,并将向大众提出这个问题

我目前的计划是,当第一个用户(可能是我)进入站点时,它会启动一个后台线程,等待分配的时间(每小时一次),然后启动阻止其他用户的事件(我是一名Windows程序员,所以我从事件和WaitOnMultipleObjects的角度考虑),直到完成


Jeff是如何在Asp.Net中做到这一点的?他的方法是否适用于Java web应用程序世界?

Jeff的机制是创建某种缓存对象,Asp.Net会在某个时间间隔自动重新创建该对象-这似乎是一个Asp.Net特定的解决方案,因此在Java世界中可能不会对您(或我)有多大帮助

阿特伍德:嗯,我最初是在推特上问的,因为我只是想要一些轻的东西。我真的不想写一个windows服务。我觉得那是带外码。加上实际执行工作的代码实际上是一个网页,因为对我来说,网站上的一个逻辑工作单元就是一个网页。所以,这真的就像我们回拨到网站,就像网站中的另一个请求,所以我认为它应该保持内联,我们在Twitter上向我推荐的一个小方法是,本质上在应用程序缓存中添加一些具有固定过期期的内容,然后,您有一个回调,因此当该回调过期时,它将调用执行该工作的特定函数,然后您将它以相同的过期时间添加回缓存。所以,有一点,也许“犹太人区”是个合适的词

我的方法一直是让操作系统(即Cron或Windows任务调度器)每隔一段时间加载一个特定的URL,然后在该URL上设置一个页面来检查它的队列,并执行所需的任何任务,但我很想知道是否有更好的方法

从文字记录来看,FogBugz似乎也使用windows服务加载URL方法

斯波尔斯基:我们有一个叫做heartbeat.asp的特殊页面。而那个页面,无论何时你点击它,任何人都可以随时点击:不痛。但当该页面运行时,它会检查一个等待任务队列,以查看是否有任何需要执行的操作。如果有什么事情需要做,它会做一件事,然后再次查看队列,如果还有其他事情需要做,它会返回一个加号,而它返回的整个网页只是一个加号字符。如果没有其他事情要做,队列现在是空的,它返回一个负号。因此,任何人都可以调用它并多次点击它,您可以在web浏览器中加载heartbeat.asp您可以点击Ctrl-R Ctrl-R Ctrl-R Ctrl-R Ctrl-R,直到开始得到负数而不是正数。完成后,FogBugz将完成所有需要进行的维护工作。这是第一部分,第二部分是一个非常非常简单的Windows服务,它可以运行,它的全部任务是调用heartbeat.asp,如果它得到一个加号,很快再调用它,如果它得到一个减号,再调用它,但暂时不要。所以基本上有一个Windows服务一直在运行,它有一个非常非常简单的任务,只需点击一个URL,看看它是加号还是减号,然后根据它是加号还是减号来安排何时再次运行。很明显,你可以在这个主题上做任何你想做的变化,比如,你实际上可以,而不是只返回一个加号或减号,你可以说“好的,60秒后给我回电话”或“马上给我回电话,我还有更多的工作要做。”这就是它的工作原理。。。所以它只是运行维护服务,你知道,它就像,你知道,运行维护服务的半页代码,它永远不需要改变,它没有任何逻辑,它只是包含了使这些网页以一定的保证频率被调用的挠痒。在heartbeat.asp的网页中,有一个代码,它维护一个需要完成的任务队列,并查看经过了多少时间,并且,你知道,深夜维护和每七天删除所有标记为垃圾邮件的旧邮件以及所有类型的仅维护后台任务。这就是为什么


下面是他们在StackOverflow.com上的做法:


我认为开发用于运行后台任务的自定义解决方案并不总是值得的,因此我建议在Java中使用

在您的情况下(需要在web应用程序中运行后台任务),您可以使用发行版中包含的ServletContextListener来执行

在此之后,您可以启动(触发)后台任务(作业),例如,您可以使用日历或类似cron的表达式。在您的情况下,您很可能应该解决这个问题,它允许您以固定的、有规律的间隔运行作业


在Quartz中也可以很容易地描述作业本身,但是您没有提供有关需要运行什么的任何详细信息,因此我无法在这方面提供建议。

如前所述,Quartz是一种标准解决方案。如果您不关心后台任务在重启期间的集群或持久性,那么可以使用内置的线程池支持(在Java5,6中)。如果使用,可以将可运行程序放入后台线程池中,在执行之前等待特定的时间

如果您确实关心集群和/或持久性,那么您可以使用JMS队列进行异步执行,尽管您仍然需要某种方式来延迟后台任务(您可以使用Quartz或ScheduledExecutorService来完成此任务)。

我们使用JMS队列来执行定时后台任务