Java 库类来处理“回调”的计划执行?
我的程序有一个称为调度程序的组件,它允许其他组件注册它们想要回调的时间点。 这应该像 Unix cron 服务一样工作,即你告诉调度程序“在每个整点过十分钟通知我”。
我意识到 Java 中没有真正的回调。
这是我的方法,是否有一个图书馆已经做了这些事情? 也请随意提出改进建议。
注册对调度程序的调用传递:
- 时间规范,包含小时、分钟、秒、年月、dom、dow,其中每一项可以未指定,意思是“每小时/每分钟等执行一次”。 (就像 crontabs 一样)
- 一个包含数据的对象,这些数据将告诉调用对象在收到调度程序通知时要做什么。 调度程序不处理这些数据,只是存储它并在收到通知时将其传回。
- 对调用对象的引用
启动时或新的注册请求后,调度程序从当前系统时间的日历对象开始,并检查数据库中是否有任何与该时间点匹配的条目。 如果有,则执行它们并重新开始该过程。 如果没有,Calendar 对象中的时间将增加一秒,并重新检查 entreis。 重复这一过程,直到有一个或多个条目匹配为止。 (离散事件模拟)
调度程序将记住该时间戳,每秒睡眠和唤醒以检查它是否已经存在。 如果它碰巧醒来并且时间已经过去,则它会重新开始,同样,如果时间已到并且作业已执行。
编辑:感谢您向我指出 Quartz。 然而,我正在寻找更小的东西。
My program has a component - dubbed the Scheduler - that lets other components register points in time at which they want to be called back. This should work much like the Unix cron service, i. e. you tell the Scheduler "notify me at ten minutes past every full hour".
I realize there are no real callbacks in Java.
Here's my approach, is there a library which already does this stuff? Feel free to suggest improvements, too.
Register call to Scheduler passes:
- a time specification containing hour, minute, second, year month, dom, dow, where each item may be unspecified, meaning "execute it every hour / minute etc." (just like crontabs)
- an object containing data that will tell the calling object what to do when it is notified by the Scheduler. The Scheduler does not process this data, just stores it and passes it back upon notification.
- a reference to the calling object
Upon startup, or after a new registration request, the Scheduler starts with a Calendar object of the current system time and checks if there are any entries in the database that match this point in time. If there are, they are executed and the process starts over. If there aren't, the time in the Calendar object is incremented by one second and the entreis are rechecked. This repeats until there is one entry or more that match(es). (Discrete Event Simulation)
The Scheduler will then remember that timestamp, sleep and wake every second to check if it is already there. If it happens to wake up and the time has already passed, it starts over, likewise if the time has come and the jobs have been executed.
Edit: Thanks for pointing me to Quartz. I'm looking for something much smaller, however.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
查找 Quartz
Lookup Quartz
如果您的对象确切地知道它们希望执行的各个时间点,那么您可以使用
java.util.concurrent.ScheduledExecutorService
。 然后他们简单地调用:如果您希望调度程序本身处理“每 5 秒执行一次”之类的功能,或者您想要围绕错过执行或持久性进行复杂的行为,则只需使用 Quartz执行审计跟踪。
实际上,您可以简单地重用 Quartz 的 CronTrigger 类来获取“下一个执行时间”。 该类是完全独立的,不依赖于从 Quartz“上下文”中调用。 一旦您获得
Date
或long
形式的下一个执行时间,您就可以像上面一样使用 JavaScheduledExecutorService
If your objects know exactly the individual points in time which they wish to be executed, then you could use a
java.util.concurrent.ScheduledExecutorService
. Then they simple call:You'd only need to use
Quartz
if you want the scheduler itself to handle functionality like "execute every 5 seconds", or if you want complex behaviour around missed executions, or the persistence of the execution audit trail.You can actually trivially re-use Quartz's
CronTrigger
class to get a "next execution time". The class is completely standalone and does not depend on being invoked from within theQuartz
"context". Once you have the next execution time as aDate
orlong
, you can just use the JavaScheduledExecutorService
as above如果您的需求很简单,请考虑使用 java.util。计时器:
正如所述,ExecutorService java.util.concurrent< /a> 如果您需要的话,可以提供更丰富的 API。
If your needs are simple, consider using java.util.Timer:
As has been noted, the ExecutorService of java.util.concurrent offers a richer API if you need it.
Quartz 是该领域中最强大且明显的强者,但还有一些替代方案可供探索。
Cron4j 是一个足够不错的库,比 Quartz 更轻量级。 它提供了很好的文档并且会做你想做的事。
可能更有趣的是,如果您想使用更适合 Java 并发库(特别是 Executors 和 ScheduledExecutors)的库,那么 HA-JDBC 有一个 CronExecutorService 接口,由其 CronThreadPoolExecutor 实现。 现在,有趣的是,它依赖于 Quartz(提供 CronExpression 类),但我发现两者一起工作比单独使用 Quartz 效果更好。 如果您不想要大量的依赖项,可以轻松地从 Quartz 和 HA-JDBC 中提取一些类来实现这一点。
由于您想要更小的东西(刚刚注意到您的编辑),请从 Quartz 获取 CronExpression 以及我上面提到的两个 HA-JDBC 类。 这样就可以了。
Quartz is the big and obvious powerhouse in this area, but there are some alternatives to explore.
Cron4j is a decent enough library, that is a little more lightweight than Quartz. It provides good documentation and will do what you want.
Probably more interesting is if you want to use a library that fits better with Java's concurrency libraries (particularly Executors and ScheduledExecutors) then HA-JDBC has a CronExecutorService interface, implemented by its CronThreadPoolExecutor. Now, interestingly, it has a dependency on Quartz (to provide the CronExpression class), but I find that the two together work better than just Quartz alone. If you don't want large dependencies, its easy to extract the handful of classes from Quartz and HA-JDBC that make this happen.
Since you want something much smaller (just noticed your edit), grab CronExpression from Quartz, and the two HA-JDBC classes I mentioned above. That'll do it.
我强烈推荐 cron4j (已经提到过)而不是 Quartz,除非你绝对需要更多Quartz 的高级和复杂功能。 Cron4j 很好地专注于它应该做的事情,有不错的文档,并且不是一个厨房水槽解决方案。
I would strongly recommend cron4j (already mentioned) over Quartz, unless you absolutely need some of more advanced and complex features of Quartz. Cron4j focuses nicely on what it is supposed to do, has decent documentation, and is not a kitchen-sink solution.
通常推荐使用 Quartz 调度程序。
Quartz scheduler is usually recommended.
不敢相信 java.util.Timer 被选为答案。 石英确实是一个更好的选择。
与 java.util.Timer 相比,quartz 的一大优点是,使用quartz,作业可以存储在数据库中。 因此,一个 jvm 可以调度,而另一个 jvm 可以执行。 而且(显然)该请求在 jvm 重新启动后仍然存在。
Can't believe java.util.Timer was voted as the answer. Quartz is really a much better choice.
A big advantage of quartz over java.util.Timer is that with quartz the jobs can be stored in the db. As a result one jvm can schedule and another can execute. Also (obviously) the request survives across jvm restarts.
我只是想说,我尝试提取这些类,并且成功了! 我需要这三个类:
我只需要做这些小调整:
我很高兴我没有陷入混乱的依赖关系中。 恭喜班级作者!
而且它一直运作得像冠军一样。
I just wanted to say that I tried extracting these classes, and it worked! I needed these three classes:
And I only had to do these minor tweaks:
I was thrilled that I didn't get stuck pull in a tangle of dependencies. Congrats to the class authors!
And it's been working like a champ.