我花了很多时间研究这个,有很多方法可以了解 Java 背景(我特别关注 Java 8 解决方案,应该注意)。
好的,这是我的(通用)情况 - 请注意这是一个示例,所以不要花时间研究它的工作方式/它在做什么:
一些模糊的代码结构:
@GET
@ // api definitions
public Response myAPIMethod(){
// get data from datastore
Object o = getData();
// submit request to cache data, without blocking
saveDataToCache();
// return the response to the Client
return Response.ok(data).build();
}
在后台运行
saveDataToCache
而无需在返回 data
之前等待的“最佳”(最佳、最安全、标准)方式是什么?请注意,此缓存不应发生太频繁(可能每秒发生几次)。我尝试了几种方法,特别是 CompletableFutures,但是当我输入一些日志时,它似乎总是在返回响应之前等待(我没有调用
get
)。基本上来自客户端的连接可能会在缓存调用完成之前关闭 - 但我希望它已经完成:) 我不确定规则是否与客户端连接的生命周期相同。
预先感谢您的任何建议,如果有任何不清楚的地方,请告诉我......我试图以一种对那些没有我正在尝试做的领域知识的人可以理解的方式来定义它(我无法透露)。
最佳答案
根据评论,缓存 API 已经是异步的(它实际上返回一个 Future
)。我想它创建和管理一个内部 ExecutorService
或在启动时接收一个。
我的观点是不需要处理要缓存的对象,而是处理返回的 Future
s。异步行为实际上是由缓存客户端提供的。
一种选择是忽略此客户端返回的 Future
。这种方法的问题在于,在尝试将对象存储在缓存中时发生错误时,您失去了采取纠正措施的机会。事实上,你永远不会知道出了什么问题。
另一种选择是处理返回的 Future
。一种方法是使用 Queue
,正如另一个答案中所建议的那样,尽管我会使用 ConcurrentLinkedQueue
代替,因为它是无界的,并且您已经提到将对象添加到缓存中的情况每秒会发生两次。您可以在缓存客户端返回时立即将 offer()
Future
到队列中,然后在另一个线程中,这将运行无限循环,您可以为 poll()
Future
队列,如果返回非空值,则调用isDone()
就可以了。 (如果队列返回 null,则表示它是空的,因此您可能需要 hibernate 几毫秒)。
如果 isDone()
返回 true
,您可以在 future 安全地调用 get()
,它被一个 try/catch
块包围,该块可以捕获任何 ExecutionException
并根据需要对其进行处理。 (您可以重试对缓存的操作,记录发生的事情等)。
如果 isDone()
返回 false
,您可以简单地将 offer()
Future
再次放入队列。
现在,我们在这里讨论的是处理来自缓存异步操作的错误。我不会做任何事情,让缓存客户端返回的 future 安然无恙。如果出现问题,可能发生的最糟糕的事情是您必须再次访问数据存储区以检索对象。
关于java - 后台任务然后在Java任务完成之前结束连接(8),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28661922/