如何使用Java定时器放弃快速连续完成的所有任务(最后一个任务除外)
如果我没有正确解释这一点,请帮助我纠正我的问题。我的问题可能与Java定时器有关,也可能与一般问题解决有关 亲爱的读者,您不需要理解什么是OpenHAB,什么是OpenHAB规则,或者实际上MQTT是做什么的。但无论如何,我会用这些术语来设置我的问题的场景 在OpenHAB中,我有一个规则,用于响应发布到MQTT主题的消息。当我关闭调光器时,会向代理发送一组down MQTT消息。每条消息触发一条OpenHAB规则,该规则读取灯光的当前值并减去1,然后将其写回 为了确保规则不会在不同线程中同时触发,从而防止灯光以正确的速率变暗,我的一位同事建议我添加lock.lock,如下所示:如何使用Java定时器放弃快速连续完成的所有任务(最后一个任务除外),java,timer,openhab,Java,Timer,Openhab,如果我没有正确解释这一点,请帮助我纠正我的问题。我的问题可能与Java定时器有关,也可能与一般问题解决有关 亲爱的读者,您不需要理解什么是OpenHAB,什么是OpenHAB规则,或者实际上MQTT是做什么的。但无论如何,我会用这些术语来设置我的问题的场景 在OpenHAB中,我有一个规则,用于响应发布到MQTT主题的消息。当我关闭调光器时,会向代理发送一组down MQTT消息。每条消息触发一条OpenHAB规则,该规则读取灯光的当前值并减去1,然后将其写回 为了确保规则不会在不同线程中同时触
rule "ArduinoBedroomVector"
when
Item Bedroomvector received update
then
lock.lock()
try {
// rules here
var Number lightcircuit1level = BedroomCeilingLight.state as DecimalType
switch(Bedroomvector.state) {
case "light_1_up" : {
lightcircuit1level = lightcircuit1level + 3
if(lightcircuit1level>100) lightcircuit1level = 100
sendCommand(BedroomCeilingLight, lightcircuit1level);
}
case "light_1_down" : {
lightcircuit1level = lightcircuit1level -3
if(lightcircuit1level<0) lightcircuit1level = 0
sendCommand(BedroomCeilingLight, lightcircuit1level);
}
}
}
finally {
lock.unlock()
}
end
这是一种享受
现在,我的执行器不会错过向下的消息
但是,由于执行器在433MHz射频传输过程中需要一段时间来响应每个单独的消息,因此发送每个射频消息需要0.5秒,发送到执行器的调光命令正在排队
因此,我需要介绍一种检查规则是否在最后运行的方法,例如0.6秒。如果有,则增加值,但不发送命令。如果没有,则增加值并最终发送命令
例如,这意味着我可以不断地上下调暗灯光,只要我不停下来,灯光级别就不会改变。然后,一旦我决定停止向上或向下调光,灯光级别将最终确定并设置
更好的是一个计时规则,允许我不断地改变水平,但仅根据最新水平每0.5秒设置一次灯光水平
我确信这只是创建一个在运行规则时被检查的计时器的一个例子,但是我不能确定何时应该创建和检查计时器。这对许多人来说可能是显而易见的。不要对自己太苛刻,这不是显而易见的 我的方法是保留规则最近执行的时间戳,并在调用sendCommand之前添加一个if语句,以检查是否至少经过了.6秒 然而,有一种情况是,若最后一次收到命令的时间是在.6秒之前,那个么新值将永远不会被发送,所以我们需要设置一个计时器来发布最后一个值。但是,我们需要清理计时器,以便在设置计时器后收到新命令但尚未启动时,它不会启动。边缘案例很混乱
var lastExec = now.millis
var Timer timer = null
rule "ArduinoBedroomVector"
when
Item Bedroomvector received update
then
lock.lock()
try {
// rules here
var Number lightcircuit1level = BedroomCeilingLight.state as DecimalType
switch(Bedroomvector.state) {
case "light_1_up" : {
lightcircuit1level = lightcircuit1level + 3
if(lightcircuit1level>100) lightcircuit1level = 100
// Wait to send the new value
}
case "light_1_down" : {
lightcircuit1level = lightcircuit1level -3
if(lightcircuit1level<0) lightcircuit1level = 0
// wait to send the new value
}
}
// if more than .6 seconds have passed since the last time the value was sent
if((now.millis - lastExec) > 600){
// cancel the timer if one is already set
if(timer != null) {
timer.cancel
timer = null
}
sendCommand(BedroomCeilingLight, lightcircuit1level)
lastExec = now.millis
}
// its too soon to send the update, set a timer
else {
// cancel the timer if one is already set
if(timer != null) {
timer.cancel
timer = null
}
// set a timer to go off in what is left of the .6 secs since the last update
var t = now.plusMillis(600) - lastExec
timer = createTimer(now.plusMillis(t), [|
sendCommand(BedroomCeilingLight, lightcircuit1level)
lastExec = now.millis
// beware, there could be a race condition here as the timer
// will execute outside of the lock. If the rule executes
// at the same time as the timer the most recent value of
// lastExec may be overwritten with an older value. It should
// happen very rarely though and may not be a problem.
]
}
}
finally {
lock.unlock()
}
end