我使用drop wizard创建了一个post endpoint。
@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON=new JSONObject(request);
JSONArray urls=requestJSON.getJSONArray("urls");
process(urls); // this takes around 10 minutes to complete
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}
喜
process(urls);
大约需要10分钟才能完成。因此,如果我们称之为终点,则需要10分钟以上才能获得响应。
我希望process(urls);
在收到urls
的{{1}}后在后台运行。因此,当用户点击此网址时,用户将在几秒钟内得到响应。
我用线程尝试了以下代码。
request
这里我使用了一个线程。因此它以异步方式运行,用户在几秒钟内获得响应,@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON=new JSONObject(request);
JSONArray urls=requestJSON.getJSONArray("urls");
Thread thread = new Thread() {
public void run() {
process(urls); // this takes around 10 minutes to complete
}
};
thread.start();
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}
在后台运行。
这解决了我的问题。但这是正确的方法吗?如果我使用这种方法有任何问题,因为每分钟都会有很多请求。
process(urls);
中是否有任何技术可以处理这种异步性质?
答案 0 :(得分:0)
欢迎来到 Java8 ,Dropwizard用户应该推广使用 CompletableFuture 进行异步处理,因为它是处理异步处理的最安全,最酷的方式。使用 CompletableFuture ,您可以将重量级任务移动到后台线程,同时继续执行轻量级任务,从而也可以将响应发送回客户端。
@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON=new JSONObject(request);
JSONArray urls=requestJSON.getJSONArray("urls");
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// perform heavyweight task
process(urls); // this takes around 10 minutes to complete
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// perform lightweight task
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed",
Response.Status.INTERNAL_SERVER_ERROR);
}
}
CompletableFuture 在各个方面都有助于将第一个复杂任务的返回值用于第二个功能,或者通过它提供的各种方法通知故障
runAsync()
supplyAsync()
thenApply()
thenAccept()和 thenRun()
格外()
handle()
您还可以使用 thenCompose()和 thenCombine()链接 CompletableFuture ,当一项任务依赖于其他任务时,将使用该 CompletableFuture 。