我使用具有Event系统的外部框架,为简单起见,我们说它就像:
public interface EventListener {
public void eventA(int a);
public void eventB(int a, long b);
}
因此,事件系统的属性是在事件A之后,可能会或可能不会有针对该事件的事件B。但如果有一个事件B,它需要在3000毫秒内。
我不确定这个问题有什么干净的解决方案,我查看了java.util.concurrency
包,但我找不到任何能为这个问题提供干净解决方案的方法。我以为我可能会使用Future<?>
,但我无法想出一个很好的解决方案。
我会用伪代码写下我想要做的事情:
public void eventA(int a) {
// fired Event A
if (within the next 3 seconds there was an eventB for _exactly_ this a)
doSomething(a, b)
else
doSomething(a)
}
public void eventB(int a, long b) {
}
到目前为止,我使用了一个ConcurrentHashmap<Int, Long>
来存储来自eventB的所有ab组合,并检查在过去的3000毫秒内我是否在eventA
中得到了这样的ab组合,但我真的不高兴用那个解决方案。我觉得Java 1.5高级并发API需要更清晰的方法。
对于解决该问题的任何提示,我会感到高兴。
答案 0 :(得分:1)
我不完全确定你是否需要它像这样工作,但它背后的逻辑是当触发eventB时,它将数据添加到ConcurrentHashMap,并安排自己在3秒后删除。当触发eventA时,它会从地图中删除数据(从而清除该键的事件),如果有事件,则调用doSomething(int,long),否则调用doSomething(int)。
import java.util.concurrent.*;
public class EventListenerImpl implements EventListener {
// You can change how many threads there are, or use a scheduler that's
// already in the application.
private final static ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
private ConcurrentHashMap<Integer, Data> data = new ConcurrentHashMap<Integer, Data>();
@Override
public void eventA(int a) {
Data b = data.remove(a);
if (b != null) {
doSomething(a, b.getB());
} else {
doSomething(a);
}
}
@Override
public void eventB(final int a, final long b) {
final Data thisData = new Data(a);
// Needs to be synchronized because it may be removed by a scheduled event
synchronized (data) {
Data d = data.put(a, thisData);
if (d != null) {
d.getFuture().cancel(true);
}
}
thisData.setFuture(scheduler.schedule(new Runnable() {
@Override
public void run() {
data.remove(a, thisData);
}
}, 3, TimeUnit.SECONDS));
}
private class Data {
private long b;
private ScheduledFuture<?> future;
public Data(long b) {
this.b = b;
}
public long getB() {
return b;
}
public void setFuture(ScheduledFuture<?> future) {
this.future = future;
}
public ScheduledFuture<?> getFuture() {
return future;
}
}
}
让我知道这是不是你需要的,因为我有点困惑,最后猜测你想要做什么。例如,如果a
不是某种键,那么这可以大大简化......如果eventA在调用doSomething之前等待三秒钟,而不是跟踪最后三秒钟,也可以简化它次。
答案 1 :(得分:0)
使用包含每个收到的事件A的地图,包含收到Foo
的时间和潜在A
的对象(我们称之为B
)最初null
。
当您收到事件A
时,使用当前时间和空Foo
创建一个B
实例,将其存储在地图中,然后启动一个休眠的线程3秒,然后检查与Foo
关联的A
是否包含B
,从地图中删除条目,并相应地采取行动(即使用适当的参数调用doSomething
)。
当您收到B
时,检查地图中是否有Foo
以及是否收到的时间少于3秒(尽管不应该发生),并存储B
中的Foo
。
当然,您必须在需要时进行同步。