这是非常常见的传感器数据处理问题。
为了同步和合并来自不同来源的传感器数据,我想用Java实现它,而不需要太复杂的第三个库或框架。
说,我定义了一个对象(O),它由例如4个属性(A1,... A4)组成。 4个属性来自不同的数据通道,例如套接字通道。
4个属性通常以1.0~2.0 Hz的速率到达,并且它们的到达彼此独立。
一旦有4个属性(A1,... A4)同时(在一个小时间窗口内,例如100ms),那么我从这4个属性中构造一个新对象(O)。 / p>
描述性场景如下。
A1~A4的到达时间点标有*。 对象O1~U3分别在t1,t2和t3的时间点构成。
一些属性在t2和t3之间到达,但是对于构造Object不完整,因此它们
将被删除并被忽略。 一些要求: 关于实施的一些快速想法是: 欢迎任何建议和更正! A1 * * * *
A2 * * * *
A3 * * *
A4 * * * *
--------|------------|-----------------|----------> time
t1 t2 t3
O1 O2 O3
答案 0 :(得分:0)
这不太可能解决您的问题,但它可能会指向您正确的方向。
我会先使用Google Guava的MapMaker进行首次尝试:
ConcurrentMap<Key, Bucket> graphs = new MapMaker()
.expireAfterAccess(100, TimeUnit.MILLISECOND)
.makeComputingMap(new Function<Key, Bucket>() {
public Bucket apply(Key key) {
return new Bucket(key);
}
});
这将创建一个地图,如果它们在100毫秒内没有被访问,则其条目将消失,并在被要求时创建一个新的存储桶。
我无法解决的问题正是关键所在:S你真正想要的是队列形式的同类功能。
答案 1 :(得分:0)
这是另一个疯狂的想法:
使用一个LinkedBlockingQueue
来从所有传感器A1-A4
将此队列分配给AtomicReference
变量
创建一个计时器任务,该任务将以指定的时间间隔(100毫秒)将该队列切换为新队列
从旧队列中获取所有数据,看看你是否拥有所有数据A1-A4
如果是,则创建对象,否则删除所有内容
答案 2 :(得分:0)
这是另一种方法 - 它只是伪代码,你需要自己编写:)
class SlidingWindow {
AtomicReference<Object> a1;
AtomicReference<Object> a2;
AtomicReference<Object> a3;
AtomicReference<Object> a4;
Queue<Long> arrivalTimes = new Queue(4);
public Bucket setA1(Object data) {
a1.set(data);
now = System.currentTimeInMillis()
long oldestArrivalTime = arrivalTimes.pop();
arrivalTimes.push(now);
if (now - oldestArrivalTime < 100) {
return buildBucket();
}
return null;
}
public Bucket setA2(Object data) { ...
...
private Bucket buildBucket() {
Bucket b = new Bucket(a1, a2, a3, a4);
a1.clear();
a2.clear();
a3.clear();
a4.clear();
return b;
}
}
答案 3 :(得分:0)
你可以这样做,get操作阻塞直到数据到达,添加操作没有阻塞。可以稍微优化get操作,以便将候选者保持在并行结构中,这样您在过滤旧项时就不需要迭代所有候选项。但是,迭代4个项目应该足够快。
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
public class Filter<V> {
private static final long MAX_AGE_IN_MS = 100;
private final int numberOfSources;
private final LinkedBlockingQueue<Item> values = new LinkedBlockingQueue<Item>();
public Filter(int numberOfSources) {
this.numberOfSources = numberOfSources;
}
public void add(String source, V data) {
values.add(new Item(source, data));
}
public void get() throws InterruptedException {
HashMap<String, Item> result = new HashMap<String, Item>();
while (true) {
while (result.size() < numberOfSources) {
Item i = values.take();
result.put(i.source, i);
if (result.size() == numberOfSources) {
break;
}
}
//We got candidates from each source now, check if some are too old.
long now = System.currentTimeMillis();
Iterator<Item> it = result.values().iterator();
while (it.hasNext()) {
Item item = it.next();
if (now - item.creationTime > MAX_AGE_IN_MS) {
it.remove();
}
}
if (result.size() == numberOfSources) {
System.out.println("Got result, create a result object and return the items " + result.values());
break;
}
}
}
private class Item {
final String source;
final V value;
final long creationTime;
public Item(String source, V value) {
this.source = source;
this.value = value;
this.creationTime = System.currentTimeMillis();
}
public String toString() {
return String.valueOf(value);
}
}
public static void main(String[] args) throws Exception {
final Filter<String> filter = new Filter<String>(4);
new Thread(new Runnable() {
public void run() {
try {
filter.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
filter.add("a0", "va0.1");
filter.add("a0", "va0.2");
Thread.sleep(2000);
filter.add("a0", "va0.3");
Thread.sleep(100);
filter.add("a1", "va1.1");
filter.add("a2", "va2.1");
filter.add("a0", "va0.4");
Thread.sleep(100);
filter.add("a3", "va3.1");
Thread.sleep(10);
filter.add("a1", "va1.2");
filter.add("a2", "va2.2");
filter.add("a0", "va0.5");
}
}