实现代码
/**
* 滑动窗口
*/
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();
}
}
}
}