gpt4 book ai didi

java - 如何使用Guava缓存HTTP响应? (没有线程被阻塞)

转载 作者:太空宇宙 更新时间:2023-11-04 10:20:19 25 4
gpt4 key购买 nike

所以我尝试使用 Guava 缓存来缓存 HTTP 响应(使用 OkHtttp + 改造、rxjava 进行多线程)。目前看起来是这样的:

    Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://blablabla.com")
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();

apiClient = retrofit.create(Api.class);

CacheLoader<Integer, HttpResponse> cacheLoader = new CacheLoader<Integer, HttpResponse>() {
@Override
public Response load( Integer key ) throws InterruptedException, ExecutionException {
return apiClient.getHttpResponse(key)
.subscribeOn(Schedulers.io())
.blockingFirst();
}
};

responseCache = CacheBuilder.newBuilder()
.concurrencyLevel(8)
.maximumSize( 10 )
.build(cacheLoader);

apiClient 返回 Observable,并在 CacheLoader 的 load 方法中订阅它。我还设置了 concurrencyLevel(8) 但它似乎不允许同时“加载”和“读取”。

我认为 blockingFirst() 调用可能会阻塞线程,因此我无法从缓存发出并发请求,即每当缓存加载新的 http 响应时,都无法读取缓存。

我不知道如何使其异步,非常感谢任何帮助:)

最佳答案

使用Guava,您仍然可以进行异步非阻塞调用并缓存HTTP响应,但您必须在收到HTTP响应后手动调用cache.put()。所以你可以像下面这样定义你的LoadingCache。

private LoadingCache<String, ServerResponse> cache =
CacheBuilder.newBuilder()
.maximumSize(50)
.expireAfterWrite(24, TimeUnit.HOURS)
.build(
new CacheLoader<String, ServerResponse>() {
public ServerResponse load(String id) {
return null; // or empty ServerResponse
}
});

在你的调用方法中:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://blablabla.com")
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();

apiClient = retrofit.create(Api.class);

try {
ServerResponse cachedResponse = cache.get(someUniqueKey);
if (cachedResponse != null) {
// return cachedResponse here
return;
}
doNormalHttpRequest()
} catch (ExecutionException | CacheLoader.InvalidCacheLoadException e) {
doNormalHttpRequest();
}

void doNormalHttpRequest() {
apiClient.request(body).enqueue(
new retrofit2.Callback<ServerResponse>() {
@Override
public void onResponse(Call<ServerResponse> call,
Response<ServerResponse> response) {
if (response.isSuccessful()) {
cache.put(someUniqueKey, response.body();
}
}

@Override
public void onFailure(Call<ServerResponse> call, Throwable {}
});
}

作为一个额外的好处,这也可以缓存 POST 请求,因为 Retrofit 仅使用 OkHttp 的缓存实现来缓存 GET 请求。

关于java - 如何使用Guava缓存HTTP响应? (没有线程被阻塞),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51244793/

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