ExpiringSet { public boolean contains(final E key) { synchronized (set) { if (set.contains(key)) { return true; } set.add(key); } scheduler.schedule(new Runnable() { @Override public void run() { synchronized (set) { set.remove(key); } } }, expireSeconds, TimeUnit.SECONDS); return false; } ExpiringSet(int expireSeconds); boolean contains(final E key); void shutdown();  }
@Test public void testAdd() throws InterruptedException { ExpiringSet<String> expiringSet = new ExpiringSet<String>(2); assertFalse(expiringSet.contains("hello")); assertTrue(expiringSet.contains("hello")); }
@Test public void testExpire() throws InterruptedException { ExpiringSet<String> expiringSet = new ExpiringSet<String>(2); assertFalse(expiringSet.contains("hello")); assertTrue(expiringSet.contains("hello")); Thread.sleep(3 * 1000); assertFalse(expiringSet.contains("hello")); assertTrue(expiringSet.contains("hello")); }
@Test public void testLiveExpire() throws InterruptedException { ExpiringSet<String> expiringSet = new ExpiringSet<String>(2); assertFalse(expiringSet.contains("hello")); assertTrue(expiringSet.contains("hello")); int i = 0; while (i++ < 1000000) { if (!expiringSet.contains("hello")) { break; } Thread.sleep(1); } assertTrue(expiringSet.contains("hello")); assert(i > 1000); assert(i < 1000000); }