package com.interview.flag.o; import java.util.Date; import java.util.concurrent.TimeUnit; /** * Created_By: stefanie * Date: 15-1-13 * Time: 下午1:36 */ public class O9_HitCounts { class Timer{ long lastTime = -1; int precision = 1; public Timer(int precision){ this.precision = precision; } public long time() { return new Date().getTime() / precision; } public long diff(){ long current = time(); long diff = 0; if(lastTime != -1) diff = current - lastTime; lastTime = current; return diff; } } class CyclicBuffer{ Timer timer; int capacity; int unit; int[] buffer; int index = 0; public CyclicBuffer(int capacity, int precision){ this.unit = 1000 / precision; this.capacity = capacity * this.unit + 1; buffer = new int[this.capacity]; timer = new Timer(precision); } public void append(int increment){ long shift = timer.diff(); if(shift == 0){ buffer[index] += increment; } else { int value = buffer[index] + increment; for(int i = 1; i <= shift; i++){ buffer[(index + i) % capacity] = value; } index = (int) (index + shift) % capacity; } } public int get(int secondBeforeNow){ secondBeforeNow *= this.unit; int offset = (index + capacity - secondBeforeNow) % capacity; return buffer[offset]; } } CyclicBuffer buffer = new CyclicBuffer(5 * 60, 500); //the max range is 5 minutes, record precision is 500 million seconds. public void hit(){ buffer.append(1); } public int getHitsInLastSecond(){ buffer.append(0); return buffer.get(0) - buffer.get(1); } public int getHitsInLastMinute(){ buffer.append(0); return buffer.get(0) - buffer.get(60); } public int getHitsInLastFiveMinute(){ buffer.append(0); return buffer.get(0) - buffer.get(300); } public static void main(String[] args) throws InterruptedException { O9_HitCounts counter = new O9_HitCounts(); for(int i = 0; i < 6; i++){ for(int j = 0; j < 60; j++) { TimeUnit.MILLISECONDS.sleep(900); for (int k = 0; k < 5; k++) counter.hit(); System.out.println(counter.getHitsInLastSecond()); //5 System.out.println(counter.getHitsInLastMinute()); //330 System.out.println(counter.getHitsInLastFiveMinute()); //330 * 5 } } } }