Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 番石榴的条件记忆法_Java_Caching_Guava_Memoization - Fatal编程技术网

Java 番石榴的条件记忆法

Java 番石榴的条件记忆法,java,caching,guava,memoization,Java,Caching,Guava,Memoization,我知道怎么做。然而,我只想在满足某些条件的情况下回忆。我调用的服务有时会返回一个不成功的响应。如果服务的响应成功,我只想回忆一下 MyResponse myResponse = myService.call() boolean success = myResponse.isSuccessful(); 我的缓存是这样创建的: 私有供应商缓存 private void createCache() { this.cache = Suppliers .memoizeWithEx

我知道怎么做。然而,我只想在满足某些条件的情况下回忆。我调用的服务有时会返回一个不成功的响应。如果服务的响应成功,我只想回忆一下

MyResponse myResponse = myService.call()
boolean success = myResponse.isSuccessful();
我的缓存是这样创建的:

私有供应商缓存

private void createCache() {
    this.cache = Suppliers
        .memoizeWithExpiration(myService::call, timeout,
            TimeUnit.MINUTES);
}
问题:只有在响应成功时,才可以使用传递给
memoizeWiftation
方法的供应商,以某种方式缓存响应吗?


我发现的唯一解决方法是,在检索值时,首先调用
cache.get()
,检查缓存中存储的对象是否成功,如果不成功,再次调用
createCache()
清除它,然后再次获取值。这样,如果后续服务调用返回一个有效的对象,它将被存储,如果不是,每个后续调用都将清除缓存并再次调用该服务

 public MyResponse getResponse() {
    MyResponse myResponse = cache.get();
    if (myResponse.isSuccess()) {
      return myResponse;
    } else {
      createCache();
      return cache.get();
    }
  }

然而,在这个解决方案中,如果缓存是空的,并且服务返回不成功的响应,它将立即被再次调用

您可以在服务类中或任何其他合适的位置创建一个方法
Calluntilsucces
(这里我假设它在您的服务中)。您还可以在此方法中定义最大尝试次数,之后它将返回null,这样您就可以避免无限期地调用您的服务(下面提供的代码中没有实现此建议,但这样做非常容易)。正如Guava方法所期望的那样,您甚至可以使用此逻辑创建lambda,并将其直接传递给
memoizewifthexpatition
方法

public MyResponse callUntilSuccess() {

    MyResponse response = myService.call();
    while (!response.isSuccessful()) {
        response = myService.call();
    }
    return response;
}   
然后以这种方式进行记录:

private void createCache() {
    this.cache = Suppliers
         .memoizeWithExpiration(myService::callUntilSuccess, timeout,
                TimeUnit.MINUTES);
}   

这就是你要找的吗


    private void createCache() {
        this.cache = Suppliers.memoizeWithExpiration(
           Suppliers.compose(
               response -> (response.isSuccess() ? response : null),
               myService::call
           ),
           timeout,
           TimeUnit.MINUTES
        );
    }
在这里,它将缓存响应或null,这取决于它是否成功

MyResponse myResponse = myService.call()
boolean success = myResponse.isSuccessful();
有关
compose
的更多信息,请点击此处

编辑: 如果您需要在成功时缓存该值,并在失败时将缓存留空,同时返回失败的请求,那么您自己就差不多做到了,只需在
getResponse
中稍微更改返回逻辑,如下所示:


    public MyResponse getResponse() {
        final MyResponse myResponse = cache.get();
        if (!myResponse.isSuccess()) {
            this.createCache(); // clear cache
        }
        return myResponse; // don't call .get() again!
    }


您在IMO中查看的位置不正确。您需要更改
getResponse()
中的逻辑,以便在所有情况下都不使用
cache.get()
,因为如果您成功地不进行有条件的缓存,则无法返回结果。也就是说,在
else
分支中调用
myService::call
,然后有条件地创建缓存。未缓存?->呼叫服务,成功吗?->缓存,否则返回错误,不缓存。你是对的,但我不知道是否可以调用服务,然后选择缓存响应而不再次调用服务-这就是我在这里要问的。
memoizewexpatition
方法的全部要点是服务调用隐藏在缓存的
get
方法下。因此,我将值放入缓存的唯一方法是调用调用下面的服务的
get
方法。如果你知道如何使用番石榴来实现这一点,请写一个答案,我很乐意接受。在这一点上,你偏离了番石榴的假设。备忘录代码很简单,因此您可以复制它并使用其他用例进行扩展。是的,就是这样,非常简单!。另一个人先回答,所以我接受他的回答,但我也喜欢撰写
的想法。非常感谢。