Java 同步和合并消息/数据流

Java 同步和合并消息/数据流,java,concurrency,merge,messaging,sensors,Java,Concurrency,Merge,Messaging,Sensors,它是关于非常常见的传感器数据处理问题 为了同步和合并来自不同来源的传感器数据,我想用Java实现它,而不需要太复杂的第三个libs或框架 比如说,我定义了一个对象(O),它由4个属性(A1,…A4)组成。这4个属性来自不同的数据通道,例如套接字通道 这4个属性通常以1.0~2.0 Hz的频率到达,并且它们的到达相互独立。 一旦有4个属性(A1,…A4)同时出现(在一个小时间窗口内,例如100ms),那么我将从这4个属性构造一个新对象(O) 下面是一个描述性的场景。 A1~A4的到达时间点标有*

它是关于非常常见的传感器数据处理问题

为了同步和合并来自不同来源的传感器数据,我想用Java实现它,而不需要太复杂的第三个libs或框架

比如说,我定义了一个对象(O),它由4个属性(A1,…A4)组成。这4个属性来自不同的数据通道,例如套接字通道

这4个属性通常以1.0~2.0 Hz的频率到达,并且它们的到达相互独立。 一旦有4个属性(A1,…A4)同时出现(在一个小时间窗口内,例如100ms),那么我将从这4个属性构造一个新对象(O)

下面是一个描述性的场景。 A1~A4的到达时间点标有*

对象O1~U3分别在t1、t2和t3的时间点上构造。 一些属性在t2和t3之间到达,但对于构建对象来说并不完整,因此它们 将被丢弃并忽略

  A1     *          *         *         *
  A2      *           *         *        *
  A3     *            *                  * 
  A4      *            *       *         * 
  --------|------------|-----------------|----------> time
          t1           t2                t3
          O1           O2                O3  
一些要求:

  • 识别时间点a.s.a.p.以从最后传入的4个属性构造对象
  • FIFO、O1必须在O2之前构造,以此类推
  • Java中的更少锁定
  • 如果数据未完成构建对象,则最终删除数据
  • 关于实施的一些快速想法包括:

    • 将任何传入属性存储在时间离散存储桶的FIFO队列中(每个存储桶包含4个不同的属性)
    • 同时运行一个无止境线程来检查FIFO队列(从队列的头部)是否有任何bucket已经被4个不同的属性填充。如果是,则构造一个对象并从队列中移除该bucket。如果铲斗未在特定时间窗口内完全装满,则会掉落

    欢迎任何建议和更正

    这不太可能解决您的问题,但它可能会为您指明正确的方向

    我会第一次尝试使用谷歌番石榴:

    ConcurrentMap<Key, Bucket> graphs = new MapMaker()
                                       .expireAfterAccess(100, TimeUnit.MILLISECOND)
                                       .makeComputingMap(new Function<Key, Bucket>() {
                                                         public Bucket apply(Key key) {
                                                             return new Bucket(key);
                                                         }
                                        });
    
    ConcurrentMap graphs=newmapmaker()
    .expireAfterAccess(100,时间单位。毫秒)
    .makeComputingMap(新函数(){
    公共存储桶应用(密钥){
    返回新铲斗(钥匙);
    }
    });
    
    这将创建一个映射,其条目在100毫秒内未被访问时将消失,并在请求时创建一个新的bucket


    我搞不清楚的是关键是什么:你真正想要的是队列形式的相同功能。

    这里有另一个疯狂的想法:

    使用一个
    LinkedBlockingQueue
    将值写入所有传感器A1-A4

    将此队列分配给
    AtomicReference
    变量

    创建计时器任务,该任务将以指定的间隔(100ms)将此队列切换为新队列

    从旧队列中获取所有数据,并查看是否拥有所有数据A1-A4


    如果是,则创建对象,否则删除所有内容这是另一种方法-不过这只是伪代码,您需要自己编写:)

    类滑动窗口{
    原子参考a1;
    原子参考a2;
    原子参考a3;
    原子参考a4;
    队列到达时间=新队列(4);
    公共存储桶集合A1(对象数据){
    a1.设置(数据);
    现在=System.currentTimeInMillis()
    long-OldEstarivalTime=arrivalTimes.pop();
    到达时间。推(现在);
    如果(现在-OldEstarivalTime<100){
    返回buildBucket();
    }
    返回null;
    }
    公共存储桶集合A2(对象数据){。。。
    ...
    私有Bucket buildBucket(){
    铲斗b=新铲斗(a1、a2、a3、a4);
    a1.清除();
    a2.清除();
    a3.清晰();
    a4.清除();
    返回b;
    }
    }
    
    您可以这样做,get操作会一直阻塞直到数据到达,add操作不会阻塞。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");
    
        }
    
    
    }
    
    import java.util.HashMap;
    导入java.util.Iterator;
    导入java.util.concurrent.LinkedBlockingQueue;
    公共类过滤器{
    私人静态最终长最大使用年限(单位:MS)=100;
    私人最终信息来源;
    私有最终LinkedBlockingQueue值=新LinkedBlockingQueue();
    公共筛选器(int numberOfSources){
    this.numberOfSources=numberOfSources;
    }
    公共void添加(字符串源,V数据){
    添加(新项目(来源、数据));
    }
    public void get()抛出InterruptedException{
    HashMap结果=新建HashMap();
    while(true){
    while(result.size()MAX_AGE_IN_MS){
    it.remove();
    }
    }
    if(result.size()==numberOfSources){
    System.out.println(“获取结果,创建结果对象并返回项”+result.values());
    打破
    }
    }
    }
    私人类项目{
    最终字符串源;
    最终V值;
    最终创作时间长;
    公众的
    
    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");
    
        }
    
    
    }