java使用滑动窗口算法实现将kafka实时数据中相同分组1秒内数据打包发送

实现代码



/**
 * 滑动窗口
 */
public class SlidingWindow {
    private final Logger logger = LoggerFactory.getLogger(SlidingWindow.class);
    /**
     * 滑动窗口
     */
    private volatile ClassEntity data[];
    /**
     * 滑动窗口总数量
     */
    private int slidingWindowTotalNum;

    /**
     * 起始位置
     */
    private final AtomicInteger beginIndex = new AtomicInteger(0);
    /**
     * 最新位置索引
     */
    private final AtomicInteger latestIndex = new AtomicInteger(0);

    private LinkedBlockingQueue<byte[]> n = new LinkedBlockingQueue(1024);

    private Object putLock = new Object();

    private Object getLock = new Object();
    private volatile Long fullTime = null;


    public SlidingWindow(StringRedisTemplate stringRedisTemplate) {
        //this.stringRedisTemplate = stringRedisTemplate;
        init();
    }

    //初始化
    private void init() {
        slidingWindowTotalNum = 1024;
        data = new ClassEntity[slidingWindowTotalNum];
    }

    //放数据
    public void put(ClassEntity entity) {
        synchronized (putLock) {
            final int index = latestIndex.get();
            if (data[index] == null) {
                //logger.info("put deviceId={} index={}", entity.getDeviceId(), latestIndex);
                data[index] = entity;
                //stringRedisTemplate.opsForValue().setBit("deviceId:" + entity.getDeviceId(), index, true);
                int index2 = latestIndex.incrementAndGet();

                if (index2 >= slidingWindowTotalNum) {
                    index2 = index2 % slidingWindowTotalNum;
                    latestIndex.getAndSet(index2);
                }
            } else {
                //如果原来位置满了,就放到下下个位置,下下个位置为空进行放入,不为空提示满了
                int index2 = index + 1;
                if (index2 >= slidingWindowTotalNum) {
                    index2 = index2 % slidingWindowTotalNum;
                }
                if (data[index2] == null) {
                    latestIndex.incrementAndGet();
                    latestIndex.getAndSet(index2);
                    put(entity);
                } else {
                    if (fullTime == null) {
                        fullTime = new Date().getTime();
                    }
                    logger.info("full....beginIndex={} latestIndex={}   deviceId={} fullTime={}", beginIndex, latestIndex, entity.getDeviceId(), fullTime);
                    print(entity.getDeviceId());
                }
            }
        }


    }

    //打印数组中的数据
    public void print(Long deviceId) {
        try {

            if (deviceId == null) {
                return;
            }
            StringBuilder sb = new StringBuilder();
            int index = beginIndex.get();
            int index2 = latestIndex.get();
            if (index == index2) {
                if (index == 0) {
                    sb.append(data[slidingWindowTotalNum - 1] != null ? 1 : 0);
                } else {
                    sb.append(data[index - 1] != null ? 1 : 0);
                }

                sb.append(data[index] != null ? 1 : 0);

                if ((index + 1) > slidingWindowTotalNum) {
                    index = (index + 1) % slidingWindowTotalNum;
                    sb.append(data[index] != null ? 1 : 0);
                } else {
                    sb.append(data[index + 1] != null ? 1 : 0);
                }
                logger.info("program1 deviceId={}: {}", deviceId, sb.toString());
            } else {
                if (index == 0) {
                    sb.append(data[slidingWindowTotalNum - 1] != null ? 1 : 0);
                } else {
                    sb.append(data[index - 1] != null ? 1 : 0);
                }
                sb.append(data[index] != null ? 1 : 0);

                if ((index + 1) > slidingWindowTotalNum) {
                    index = (index + 1) % slidingWindowTotalNum;
                    sb.append(data[index] != null ? 1 : 0);
                } else {
                    sb.append(data[index + 1] != null ? 1 : 0);
                }

                sb.append("====================================================");
                if (index2 == 0) {
                    sb.append(data[slidingWindowTotalNum - 1] != null ? 1 : 0);
                } else {
                    sb.append(data[index2 - 1] != null ? 1 : 0);
                }
                sb.append(data[index2] != null ? 1 : 0);
                if ((index2 + 1) > slidingWindowTotalNum) {
                    index2 = (index2 + 1) % slidingWindowTotalNum;
                    sb.append(data[index2] != null ? 1 : 0);
                } else {
                    sb.append(data[index2 + 1] != null ? 1 : 0);
                }
                logger.info("program1 deviceId={}: {}", deviceId, sb.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //取数据
    public List<ClassEntity> get() {
        synchronized (getLock) {
            List<ClassEntity> list = new ArrayList<>();
            final int index = latestIndex.get();
            final int beginIndex = this.beginIndex.get();
            if (beginIndex == index && data[index] == null) {
                return null;
            } else {
                if (beginIndex >= index) {
                    //第一步
                    for (int i = beginIndex; i < slidingWindowTotalNum; i++) {
                        if(data[i]!=null){
                            list.add(data[i]);
                            data[i] = null;
                        }

                    }
                    //第二步
                    for (int i = 0; i < index; i++) {
                        if(data[i]!=null){
                            list.add(data[i]);
                            data[i] = null;
                        }
                    }
                    //取完数据进行滑动,起始位置和结束位置设置到一起,并且更新开始时间为当前时间,结束时间为null
                    this.beginIndex.getAndSet(index);

                } else if (beginIndex < index) {
                    for (int i = beginIndex; i < index; i++) {
                        if(data[i]!=null){
                            list.add(data[i]);
                            data[i] = null;
                        }
                    }
                    //取完数据进行滑动,起始位置和结束位置设置到一起,并且更新开始时间为当前时间,结束时间为null
                    this.beginIndex.getAndSet(index);

                }
            }
            return list;
        }


    }


}


# 使用

```bash

public class ClassRecordTopicListen {




    private Map<String, SlidingWindow> slidingWindowMap = new HashMap<>();

private volatile boolean forwardFlag = false;


    @KafkaListener(topics = "labelAllRecordTopic", groupId = "labelAllRecordTopic-group")
    public void labelAllRecordTopicListen(String msg) {
        if (!forwardFlag) {
            forwardFlag = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    forward();
                }
            }).start();
        }
					SlidingWindow slidingWindow = slidingWindowMap.get(msg + "");
                    if (slidingWindow == null) {
                        slidingWindow = new SlidingWindow();
                        slidingWindowMap.put(msg + "", slidingWindow);
                    }
                    slidingWindow.put(entity);

    }


    //每隔1秒执行一次,转发一次数据,从滑动窗口中取数据
    public void forward() {
        while (true) {
           
            try {
                for (Map.Entry<String, SlidingWindow> entry : slidingWindowMap.entrySet()) {
                    SlidingWindow slidingWindow = slidingWindowMap.get(entry.getKey() + "");
                    if (slidingWindow != null) {
                        slidingWindow.print(Long.valueOf(entry.getKey()));
                        List<ClassEntity> data = slidingWindow.get();
                        if (data != null && data.size() > 0) {
                           //发送。。。
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("异常:{},{}");
            }
           
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }


  
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值