所以我使用 Guava 的 CacheBuilder 作为 ConcurrentLRUCache 意味着这个缓存是线程安全的并且具有 LRU 属性,请参阅CacheBuilder Guava Docs。
我的假设是当多个线程同时启动时具有相同的键,一个 CyclicBarrier 用于此,然后一个线程将 put() 放入缓存,而其他线程等待。之后,其余线程将看到一个值已经在缓存中,而不是 put() 到缓存中。
这不适用于下面的代码,因为每个线程都会创建一个新的 Object() 并将其放入缓存中。通过运行测试并查看控制台以查看每次都创建了不同的对象来进行验证。
- 我使用
CacheBuilder 的方式有什么本质上的问题吗? - 我可以使用更好的方法吗?
- 有我可以使用的图书馆吗?
请和谢谢!
import java.util.concurrent.CyclicBarrier;
import org.junit.Test;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class GuavaLRUCacheTest {
private Cache<String, Object> concurrentLRUCache = CacheBuilder.newBuilder().maximumSize(100).concurrencyLevel(1).build();
@Test
public void test() throws Exception {
// The gate size is set based on the (number of threads to run) + (1 for the current thread).
CyclicBarrier gate = new CyclicBarrier(4);
// Same key is used for all threads
ConcurrentLRUTestThread t1 = new ConcurrentLRUTestThread(gate, "key1");
ConcurrentLRUTestThread t2 = new ConcurrentLRUTestThread(gate, "key1");
ConcurrentLRUTestThread t3 = new ConcurrentLRUTestThread(gate, "key1");
t1.start();
t2.start();
t3.start();
// Open the gate on all threads.
gate.await();
t1.join();
t2.join();
t3.join();
}
class ConcurrentLRUTestThread extends Thread {
private CyclicBarrier gate;
private String key;
public ConcurrentLRUTestThread(CyclicBarrier gate, String key) {
this.gate = gate;
this.key = key;
}
@Override
public void run() {
try {
gate.await();
if (concurrentLRUCache.getIfPresent(key) == null) {
System.out.println(">>>>> "+ System.nanoTime() +" - "+Thread.currentThread().getId() + " before put " + concurrentLRUCache.getIfPresent(key));
concurrentLRUCache.put(key, new Object());
System.out.println(">>>>> "+ System.nanoTime() +" - "+Thread.currentThread().getId() + " after put " + concurrentLRUCache.getIfPresent(key));
} else{
System.out.println(">>>>> "+ System.nanoTime() +" - "+Thread.currentThread().getId() + " else " + concurrentLRUCache.getIfPresent(key));
}
} catch (Throwable x) {
System.out.println(">>>>> "+ System.currentTimeMillis() +" - "+Thread.currentThread().getId() + " ConcurrentLRUTestThread exception");
}
}
}
}