作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我使用 Guava 的 CacheBuilder 作为 ConcurrentLRUCache,这意味着该缓存是线程安全的并且具有 LRU 属性,请参阅 CacheBuilder Guava Docs 。
我的假设是,当同时启动具有相同 key 的多个线程时,将使用 CyclicBarrier,然后一个线程将 put() 放入缓存,而其他线程则等待。之后,其余线程将看到一个值已在缓存中,并且不会 put() 到缓存中。
这不适用于下面的代码,因为每个线程都会创建一个 new Object() 并将其放入缓存中。通过运行测试并查看控制台来验证每次是否创建了不同的对象。
请并谢谢!
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");
}
}
}
}
最佳答案
您首先调用cache.getIfPresent
,然后尝试调用cache.put
。这将不起作用,因为这不是作为单个原子操作完成的。多个线程可以看到缓存中缺少值,这将导致多次 cache.put
调用。解决这个问题的直接方法是创建一个包含检查和操作的关键部分。那么只有一个线程会发现缓存中没有值。幸运的是,Cache
已经包含执行此操作的方法:Cache.get(key, valueLoader)
。只需使用它来检索值即可:
public class GuavaLRUCacheTest {
private Cache 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();
concurrentLRUCache.get(key, Object::new);
} catch (Throwable x) {
System.out.println(">>>>> "+ System.currentTimeMillis() +" - "+Thread.currentThread().getId() + " ConcurrentLRUTestThread exception");
}
}
}
}
关于java - 如何使用 Guava 的 CacheBuiler 作为 ConcurrentLRUCache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38906102/
所以我使用 Guava 的 CacheBuilder 作为 ConcurrentLRUCache,这意味着该缓存是线程安全的并且具有 LRU 属性,请参阅 CacheBuilder Guava Doc
我是一名优秀的程序员,十分优秀!