关于定时上报数据的无头无尾问题

问题

场景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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值