gpt4 book ai didi

java - 如何使用 Guava 的 CacheBuiler 作为 ConcurrentLRUCache

转载 作者:行者123 更新时间:2023-12-02 03:25:54 30 4
gpt4 key购买 nike

所以我使用 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/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com