使用具有不同预期间隔的计时器执行周期性任务
我被迫使用计时器来执行定期任务,该计时器以与我想要执行此任务的周期不同的间隔调用。
请注意,超时不会 100% 准确发生;即下面代码中的 timeout(javax.ejb.Timer 计时器) 可能会以 100、98、105ms 等间隔调用。
所以,我想出了这个,这还可以。但有时任务会在预期的时间间隔过去之前执行两次,或者时间间隔变得比我预期的要长一些。
你还有比这更好的主意吗? (代码是简化的伪代码,将在 EJB 容器中使用)
import javax.annotation.Resource;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
public class TimerBean {
private static final long TASK_INTERVAL = 1530;
private static final long TIMEOUT = 100;
@Resource
private TimerService timerService;
public void startTimer() {
timerService.createTimer(100, TIMEOUT, null);
}
@Timeout
public void timeout(javax.ejb.Timer timer) {
if(isApproxTime(timer, TASK_INTERVAL)){
//do stuff
}
}
private boolean isApproxTime(Timer timer, long targetInterval) {
long modulus = timer.getNextTimeout().getTime() % targetInterval;
return modulus < TIMEOUT;
}
}
编辑:我想避免 ejb.Timer 以外的状态,因此不能选择保存上次调用的时间。
I am forced to execute a periodic task using a timer that is invoked at a different interval as the period I'd like to execute this task.
Note that the timeout does not occur 100% accurately; i.e. timeout(javax.ejb.Timer timer) in the code below might be invoked at intervals 100, 98, 105ms etc.
So, I came up with this, which is sort of okay. But occasionally the task will be executed twice before the intended interval passes, or the interval becomes a little longer than I intend.
Do you have any better idea than this?
(Code is simplified pseudo-code, will be used within a EJB container)
import javax.annotation.Resource;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
public class TimerBean {
private static final long TASK_INTERVAL = 1530;
private static final long TIMEOUT = 100;
@Resource
private TimerService timerService;
public void startTimer() {
timerService.createTimer(100, TIMEOUT, null);
}
@Timeout
public void timeout(javax.ejb.Timer timer) {
if(isApproxTime(timer, TASK_INTERVAL)){
//do stuff
}
}
private boolean isApproxTime(Timer timer, long targetInterval) {
long modulus = timer.getNextTimeout().getTime() % targetInterval;
return modulus < TIMEOUT;
}
}
EDIT: I'd like to avoid state other than ejb.Timer, so saving the time of last invocation is not an option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些确实是奇怪的要求。但到底是什么。
您可以随时创建计时器吗?如果是这样,请将任务间隔调整为目标间隔结束之前剩余的时间量,或更小的时间量。这会有所偏差,但事件之间的持续时间将大致等于您的目标。
从您的代码中,我对您对事物的控制程度没有明确的感觉。例如,是否有允许指定的TIMEOUT窗口?或者是一个单一的值被指定给你,而你却无法控制它?
如果是后者(根本无法控制),那么你所能做的就是你所做的一切。我个人会强烈反对不在这个 bean 中存储状态的要求。所讨论的状态根本不持久或任何其他会使这成为问题的状态。
These are odd requirements indeed. But what the heck.
Can you create timers whenever you want? If so, adjust the task interval to be the amount of time remaining before your target interval elapses, or some smaller amount. This will drift, but the duration between events will be roughly equal to your target.
I don't have a solid feeling from your code about how much control you have over things. For example, is there a window of TIMEOUT that you are allowed to specify? Or is a single value dictated to you, and you have no control over it whatsoever?
If it's the later (no control at all over it), then what you've put together is pretty much all you can do. I personally would push back HARD on the requirement of not storing state in this bean. The state in question is not at all persistent or anything else that would make this a problem.
Quartz 应该为您提供更准确、更可控的计时器
Quartz should give you more accurate and more controllable timers