關於定時上報數據的無頭無尾問題

問題

場景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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章