问题
场景1:一组数据有规律的上报,根据其时间间隔对其分段,判断其每一段数据的开始与结束
场景2:一个消息一旦开始上报,则会以固定时间间隔上报,消息本身并无开始结束标志,现需要判断消息开始与结束
用文字描述不太利索,直接举例说明:
第1秒:1
第2秒:1
第3秒:1
第4秒:无
第5秒:无
第6秒:1
第7秒:1
第8秒:无
第9秒:1
第10秒:1
第11秒:1
那么第一段数据就是1到3秒,第二段数据就是6到7秒,第三段数据就是9到11秒。
第1秒:1
第2秒:2
第3秒:3
第4秒:无
第5秒:无
第6秒:4
第7秒:5
第8秒:无
第9秒:6
第10秒:7
第11秒:8
第一段数据为1/2/3,第二段数据为4/5,第三段数据为6/7/8。
最重要的条件,就是时间。
如果在接下的固定时间内能收到下一个数据,那么代表这段数据并没有结束上报,反之,这段数据已经上报结束。
在上报的数据本身不能提供更多信息的情况下,只能自行处理。
思路
解决办法从时间下手,目前有两种思路:
一,以更高的频率去轮询,查询每两个相邻数据的时间间隔,判断”下一个数据是否”准时“到来,如果未准时,那么当前的数据就是一段数据的结尾;
二,利用阻塞队列的特性,判断下一个数据是否“准时”。
public class EndDemo {
public static void main(String[] args) {
// Determiner determiner = new Determiner("task1");
Blocker blocker = new Blocker("task2");
try {
for (int i = 0; i < 20; i++) {
if (i % 4 == 0) {
TimeUnit.MILLISECONDS.sleep(200);
} else {
TimeUnit.MILLISECONDS.sleep(50);
}
// determiner.check(i);
blocker.check(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 利用粒度更小的时间去轮询
*/
private static class Determiner {
private long trackTime = 0;
private Thread trackThread;
private volatile boolean startFlag;
private volatile int count;
Determiner(String taskName) {
trackThread = new Thread(() -> {
try {
while (true) {
if (startFlag) {
TimeUnit.MILLISECONDS.sleep(30);
if (System.currentTimeMillis() - trackTime > 100) {
System.out.println("end:" + count);
startFlag = false;
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, taskName);
}
void check(int counter) {
if (!trackThread.isAlive()) {
trackThread.start();
}
count = counter;
if (!startFlag && System.currentTimeMillis() - trackTime > 100) {
System.out.println("start:" + counter);
startFlag = true;
}
trackTime = System.currentTimeMillis();
}
}
/**
* 利用阻塞队列的特性
*/
private static class Blocker {
private SynchronousQueue<Integer> queue;
private Thread trackThread;
private volatile boolean startFlag;
Blocker(String taskName) {
queue = new SynchronousQueue<>(true);
trackThread = new Thread(() -> {
try {
Integer temp;
int end = 0;
while (true) {
if (startFlag) {
temp = queue.poll(150, TimeUnit.MILLISECONDS);
if (temp == null) {
System.out.println("end:" + end);
startFlag = false;
} else {
end = temp;
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, taskName);
}
void check(int counter) {
if (!trackThread.isAlive()) {
trackThread.start();
}
if (!startFlag && queue.isEmpty()) {
System.out.println("start:"+counter);
startFlag = true;
}
queue.offer(counter);
}
}
}
输出:
start:0
end:3
start:4
end:7
start:8
end:11
start:12
end:15
start:16
end:19