Created
September 22, 2011 10:15
-
-
Save isopov/1234475 to your computer and use it in GitHub Desktop.
Testing for question on SO: http://stackoverflow.com/questions/7500448/simple-java-string-cache-with-expiration-possibility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.UUID; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ConcurrentMap; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Future; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.concurrent.ScheduledFuture; | |
import java.util.concurrent.TimeUnit; | |
import com.google.common.cache.Cache; | |
import com.google.common.cache.CacheBuilder; | |
import com.google.common.cache.CacheLoader; | |
public class CacheBuilderTest { | |
private static final int NUM_TASKS = 1000; | |
private static final int NUM_EXECUTORS = 20; | |
private static final long EXPIRATION_TIME = 10L; | |
public static void main(String[] args) { | |
//Solution with expiration using a thread executor | |
{ | |
final Map<String, ScheduledFuture<String>> cacheNames = new ConcurrentHashMap<String, ScheduledFuture<String>>(); | |
ScheduledExecutorService removeExpiredService = Executors.newSingleThreadScheduledExecutor(); | |
ExecutorService exService = Executors.newFixedThreadPool(NUM_EXECUTORS); | |
List<MapTask> tasks = new ArrayList<MapTask>(NUM_TASKS); | |
for (int i = 0; i < NUM_TASKS; i++) { | |
tasks.add(new MapTask(String.valueOf(i % NUM_EXECUTORS), cacheNames, removeExpiredService)); | |
} | |
List<Future<?>> futures = new ArrayList<Future<?>>(NUM_TASKS); | |
for (MapTask task : tasks) { | |
futures.add(exService.submit(task)); | |
} | |
for (Future<?> future : futures) { | |
while (!future.isDone()) { | |
//wait | |
} | |
} | |
exService.shutdown(); | |
removeExpiredService.shutdown(); | |
} | |
//Solution with CacheBuilder | |
{ | |
Cache<String, String> cache = CacheBuilder.newBuilder() | |
.expireAfterWrite(EXPIRATION_TIME, TimeUnit.MILLISECONDS) | |
.build(new CacheLoader<String, String>() { | |
@Override | |
public String load(String key) throws Exception { | |
return UUID.randomUUID().toString(); | |
} | |
}); | |
ExecutorService exService = Executors.newFixedThreadPool(NUM_EXECUTORS); | |
List<CacheTask> tasks = new ArrayList<CacheTask>(NUM_TASKS); | |
for (int i = 0; i < NUM_TASKS; i++) { | |
tasks.add(new CacheTask(String.valueOf(i % NUM_EXECUTORS), cache)); | |
} | |
List<Future<?>> futures = new ArrayList<Future<?>>(NUM_TASKS); | |
for (CacheTask task : tasks) { | |
futures.add(exService.submit(task)); | |
} | |
for (Future<?> future : futures) { | |
while (!future.isDone()) { | |
//wait | |
} | |
} | |
exService.shutdown(); | |
} | |
} | |
private static class MapTask implements Runnable { | |
private final String cacheKey; | |
private final Map<String, ScheduledFuture<String>> cacheNames; | |
private final ScheduledExecutorService removeExpiredService; | |
public MapTask(String cacheKey, Map<String, ScheduledFuture<String>> cacheNames, | |
ScheduledExecutorService removeExpiredService) { | |
this.cacheKey = cacheKey; | |
this.cacheNames = cacheNames; | |
this.removeExpiredService = removeExpiredService; | |
} | |
public void run() { | |
while (cacheNames.containsKey(cacheKey)) { | |
//wait | |
} | |
cacheNames.put(cacheKey, removeExpiredService.schedule(new Callable<String>() { | |
public String call() throws Exception { | |
ScheduledFuture<String> remove = cacheNames.remove(cacheKey); | |
if (remove == null) { | |
throw new RuntimeException(); | |
} | |
return null; | |
} | |
}, EXPIRATION_TIME, TimeUnit.MILLISECONDS)); | |
UUID.randomUUID().toString(); | |
} | |
} | |
private static class CacheTask implements Runnable { | |
private final String cacheKey; | |
private final Cache<String, String> cache; | |
public CacheTask(String cacheKey, Cache<String, String> cache) { | |
this.cacheKey = cacheKey; | |
this.cache = cache; | |
} | |
public void run() { | |
ConcurrentMap<String, String> asMap = cache.asMap(); | |
while (asMap.containsKey(cacheKey)) { | |
//wait | |
} | |
try { | |
cache.get(cacheKey); | |
} catch (ExecutionException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment