import java.util.*; public class SlidingWindowMap { public final static int s_MaxKeyCount = 500; public final static long s_NumMSIn10Min = 10 /*min*/ * 60 /*sec/min*/ * 1000 /*ms/sec*/; public final static int s_NumberOfRequestsIn10Min_OnePerSecond = 10 /*min*/ * 60 /*sec/min*/ * 2; // 2 per second or every 500 ms public final static long s_TimeBetweenRequestsInMs = 500; // Input data members private Set m_Keys; private Iterator m_KeysIterator; private int m_MaxCount; private long m_PeriodMs; private KeyStyle m_KeyStyle; // Throttled data members private long m_LastTime; // Non-throttled data members private int m_CurrentCount; enum KeyStyle { NoThrotle, Throtle } public static void main(String[] args) throws Exception { KeyStyle ks = KeyStyle.Throtle; if(args.length == 1) { String keyStyle = args[0]; if(keyStyle.equalsIgnoreCase("-throttled")) { ks = KeyStyle.Throtle; } else if(keyStyle.equalsIgnoreCase("-nonthrottled")) { ks = KeyStyle.NoThrotle; } } Set keys = generateKeys(); SlidingWindowMap m = null; m = new SlidingWindowMap(keys, 500, s_NumMSIn10Min, ks); long start = System.currentTimeMillis(); boolean firstNullAchieved = false; // Rate is greater than 500 in 10 min. ==> 2 per second. Null's should occur for(int i=0; i keys, int maxCount, long periodMs) { this.m_Keys = keys; this.m_KeysIterator = keys.iterator(); this.m_MaxCount = maxCount; this.m_PeriodMs = periodMs; } public SlidingWindowMap(Set keys, int maxCount, long periodMs, KeyStyle keyStyle) { this(keys, maxCount, periodMs); this.m_KeyStyle = keyStyle; } /** * @return a key that has been used less than 'maxCount' times during the * past 'periodMs' milliseconds or null if no such key exists. */ public String getNextKey() { String key = null; if(this.m_KeyStyle == KeyStyle.NoThrotle) { key = getNonThrottledNextKey(); } else if(this.m_KeyStyle == KeyStyle.Throtle) { key = getThrottledNextKey(); } return key; } /** * To allow some keys to be accessible through the entire 10 min period. * Return a null for any additional requests over the rate of 0.8333 requests per second. * Every 1.2 seconds a valid key can be provided. */ private String getThrottledNextKey() { String key = null; long currentTime = System.currentTimeMillis(); if(currentTime - this.m_LastTime >= 1200) { if(this.m_KeysIterator.hasNext()) { key = this.m_KeysIterator.next(); this.m_LastTime = currentTime; } } return key; } /** * First come first serve, all keys may be used up in the first few minutes, leaving a range of * time at the end of the period that no keys are returned to any requests. */ private String getNonThrottledNextKey() { String key = null; if(this.m_CurrentCount != this.m_MaxCount) { if(this.m_KeysIterator.hasNext()) { key = this.m_KeysIterator.next(); } } return key; } }