在 Java (8) 任务完成之前后台任务然后结束连接
Background a task then end connection before task completion in Java (8)
我花了很多时间研究这个,在 Java 中有很多方法可以作为背景(我专门研究了 Java 8 种解决方案,应该注意).
好的,这是我的(一般)情况 - 请注意这是一个示例,所以不要花时间了解它 works/what 它正在做的事情:
- 有人通过 API 电话请求某事
- API 从数据存储中检索一些数据
- 但是,我想在某些缓存系统中缓存这个聚合响应
- 我需要调用缓存 API(通过 REST)来缓存此响应
- 我不想等到此调用完成后再将响应返回给原始 API 调用
一些模糊的代码结构:
@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
的 "best"(最佳、最安全、标准)方法是什么?请注意,此缓存不应经常发生(可能每秒几次)。
我尝试了几种方法,特别是 CompletableFutures,但是当我输入一些日志记录时,它似乎总是在返回响应之前等待(我没有调用 get
)。
基本上,来自客户端的连接可能会在缓存调用完成之前关闭 - 但我希望它已经完成 :) 我不确定规则是否与客户端生命周期内的规则相同连接。
提前感谢您的任何建议,如果有任何不清楚的地方,请告诉我...我试图以一种对于那些不了解我正在尝试做的事情的人可以理解的方式来定义它(我不能透露).
你可以考虑adding the objects to cache into a BlockingQueue and have a separate thread taking从队列中存入缓存。
根据评论,缓存 API 已经是异步的(它实际上是 returns 一个 Future
)。我想它会创建和管理一个内部 ExecutorService
或在启动时接收一个。
我的观点是,不需要处理要缓存的对象,而是处理 返回的 Future
s。 异步行为实际上是由缓存提供的客户.
一种选择是忽略此客户端返回的 Future
。这种方法的问题在于,如果在尝试将对象存储在缓存中时发生错误,您将失去采取纠正措施的机会。事实上,您永远不会知道出了什么问题。
另一种选择是处理返回的 Future
。一种方法是使用 Queue
,如另一个答案中所建议的那样,尽管我会改用 ConcurrentLinkedQueue
,因为它是无界的 并且您提到过将对象添加到缓存中每秒两倍。您可以 offer()
将 Future
缓存客户端 returns 后立即放入队列,然后在另一个线程中,这将是 运行 一个无限循环,您可以 poll()
Future
的队列,如果返回非空值,则对其调用 isDone()
。 (如果队列 returns null 表示它是空的,那么您可能需要休眠几毫秒)。
如果isDone()
returns true
,你可以在未来安全地调用get()
,被一个try/catch
块包围,捕获任何ExecutionException
并按照您的意愿进行处理。 (您可以在缓存上重试操作,记录发生的事情等)。
如果isDone()
returns false
,你可以简单地offer()
将Future
再次加入队列。
现在,我们在这里讨论处理来自缓存缓存的异步操作的错误。我不会做任何事情,让缓存客户端返回的未来平静地过去。如果出现问题,可能发生的最糟糕的事情是您必须再次访问数据存储以检索对象。
我花了很多时间研究这个,在 Java 中有很多方法可以作为背景(我专门研究了 Java 8 种解决方案,应该注意).
好的,这是我的(一般)情况 - 请注意这是一个示例,所以不要花时间了解它 works/what 它正在做的事情:
- 有人通过 API 电话请求某事
- API 从数据存储中检索一些数据
- 但是,我想在某些缓存系统中缓存这个聚合响应
- 我需要调用缓存 API(通过 REST)来缓存此响应
- 我不想等到此调用完成后再将响应返回给原始 API 调用
一些模糊的代码结构:
@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
的 "best"(最佳、最安全、标准)方法是什么?请注意,此缓存不应经常发生(可能每秒几次)。
我尝试了几种方法,特别是 CompletableFutures,但是当我输入一些日志记录时,它似乎总是在返回响应之前等待(我没有调用 get
)。
基本上,来自客户端的连接可能会在缓存调用完成之前关闭 - 但我希望它已经完成 :) 我不确定规则是否与客户端生命周期内的规则相同连接。
提前感谢您的任何建议,如果有任何不清楚的地方,请告诉我...我试图以一种对于那些不了解我正在尝试做的事情的人可以理解的方式来定义它(我不能透露).
你可以考虑adding the objects to cache into a BlockingQueue and have a separate thread taking从队列中存入缓存。
根据评论,缓存 API 已经是异步的(它实际上是 returns 一个 Future
)。我想它会创建和管理一个内部 ExecutorService
或在启动时接收一个。
我的观点是,不需要处理要缓存的对象,而是处理 返回的 Future
s。 异步行为实际上是由缓存提供的客户.
一种选择是忽略此客户端返回的 Future
。这种方法的问题在于,如果在尝试将对象存储在缓存中时发生错误,您将失去采取纠正措施的机会。事实上,您永远不会知道出了什么问题。
另一种选择是处理返回的 Future
。一种方法是使用 Queue
,如另一个答案中所建议的那样,尽管我会改用 ConcurrentLinkedQueue
,因为它是无界的 并且您提到过将对象添加到缓存中每秒两倍。您可以 offer()
将 Future
缓存客户端 returns 后立即放入队列,然后在另一个线程中,这将是 运行 一个无限循环,您可以 poll()
Future
的队列,如果返回非空值,则对其调用 isDone()
。 (如果队列 returns null 表示它是空的,那么您可能需要休眠几毫秒)。
如果isDone()
returns true
,你可以在未来安全地调用get()
,被一个try/catch
块包围,捕获任何ExecutionException
并按照您的意愿进行处理。 (您可以在缓存上重试操作,记录发生的事情等)。
如果isDone()
returns false
,你可以简单地offer()
将Future
再次加入队列。
现在,我们在这里讨论处理来自缓存缓存的异步操作的错误。我不会做任何事情,让缓存客户端返回的未来平静地过去。如果出现问题,可能发生的最糟糕的事情是您必须再次访问数据存储以检索对象。