主线程不等待 CompletableFuture.runAsync() 并返回响应
main thread does not wait for CompletableFuture.runAsync() and returned the response
我有一个函数,它有一个 invoke 方法,它在内部调用一个 soap API,
执行大约需要 22 秒,代码中也几乎没有其他方法,
所以完全 deleteSoemthing()(下面的代码)方法需要 24 秒,
现在,我尝试 运行在单独的线程中使用计时方法,
所以我的假设是即使它是单独的线程,它也只会优化到 2 秒,因为它从总共 24 秒中花费了 22 秒。
所以可能需要 22 秒而不是 24 秒,因为它 运行ning 并行。
但是当我 运行 通过邮递员执行此操作时,执行仅需 2 秒,我的意思是响应在 2 秒内返回。并且单独的线程保持 运行ning(当我通过调试检查时)。
因此,我的疑问是,主线程是否不等待此任务完成并发回响应。
或者它只是发送响应并在后台 运行 保持异步任务
void deleteSomething(){
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
invoke("invoking a soap API"));
} catch (Exception e) {
e.printStackTrace();
}
});
//some other code
}
如果您希望主线程(请求)并行处理“一些其他代码”和“调用 SOAP API”,然后合并 return 对最终用户的响应,则这行不通。
当我们创建一个 CompletableFuture 实例时,它会在另一个线程中分离计算并立即 returns Future。如果你需要屏蔽结果,那么你需要在它上面调用get方法。但是,此过程仍需要 22+2 = 24 秒才能得到 return 响应。
为了运行这两个并行任务,你应该创建两个Callable(s)并提交给ExecutorService
例如
public void deleteSomething(){
ExecutorService executorService = Executors.newFixedThreadPool(2);
Collection<Callable<Void>> callables = new ArrayList<>();
callables.add(() -> doSomeOtherTask());
callables.add(() -> invokeSoapApi());
try {
List<Future<Void>> taskFutureList = executorService.invokeAll(callables);
taskFutureList.get(0).get();
taskFutureList.get(1).get();
} catch (InterruptedException | ExecutionException e) {
//error
}
}
public Void doSomeOtherTask() {
//some other code
return null;
}
public Void invokeSoapApi() {
//soap api call
return null;
}
请注意,线程池应在应用程序启动时创建。
所以如果你真的想使用它,那么你应该将“executorService”定义为实例变量。例如
@Service
public class MyService {
...
...
private ExecutorService executorService = Executors.newFixedThreadPool(2);
...
...
//your methods
}
这是 CompletableFuture
的预期行为,如果您查看它说的文档 -
/**
* Returns a new CompletableFuture that is asynchronously completed
* by a task running in the ForkJoinPool#commonPool() after
* it runs the given action.
*
* @param runnable the action to run before completing the
* returned CompletableFuture
* @return the new CompletableFuture
*/
你可以使用阻塞Future.get()来实现你想要的(如下图)
void deleteSomething(){
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Void> future = executorService.submit(() -> {
invoke("Invoking soap API");
return null;
});
//some other code
future.get();
}
不建议在方法中创建线程池,因为线程创建会产生开销。理想情况下,应在应用程序启动时创建线程池。
我有一个函数,它有一个 invoke 方法,它在内部调用一个 soap API, 执行大约需要 22 秒,代码中也几乎没有其他方法, 所以完全 deleteSoemthing()(下面的代码)方法需要 24 秒,
现在,我尝试 运行在单独的线程中使用计时方法, 所以我的假设是即使它是单独的线程,它也只会优化到 2 秒,因为它从总共 24 秒中花费了 22 秒。
所以可能需要 22 秒而不是 24 秒,因为它 运行ning 并行。
但是当我 运行 通过邮递员执行此操作时,执行仅需 2 秒,我的意思是响应在 2 秒内返回。并且单独的线程保持 运行ning(当我通过调试检查时)。
因此,我的疑问是,主线程是否不等待此任务完成并发回响应。 或者它只是发送响应并在后台 运行 保持异步任务
void deleteSomething(){
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
invoke("invoking a soap API"));
} catch (Exception e) {
e.printStackTrace();
}
});
//some other code
}
如果您希望主线程(请求)并行处理“一些其他代码”和“调用 SOAP API”,然后合并 return 对最终用户的响应,则这行不通。
当我们创建一个 CompletableFuture 实例时,它会在另一个线程中分离计算并立即 returns Future。如果你需要屏蔽结果,那么你需要在它上面调用get方法。但是,此过程仍需要 22+2 = 24 秒才能得到 return 响应。
为了运行这两个并行任务,你应该创建两个Callable(s)并提交给ExecutorService
例如
public void deleteSomething(){
ExecutorService executorService = Executors.newFixedThreadPool(2);
Collection<Callable<Void>> callables = new ArrayList<>();
callables.add(() -> doSomeOtherTask());
callables.add(() -> invokeSoapApi());
try {
List<Future<Void>> taskFutureList = executorService.invokeAll(callables);
taskFutureList.get(0).get();
taskFutureList.get(1).get();
} catch (InterruptedException | ExecutionException e) {
//error
}
}
public Void doSomeOtherTask() {
//some other code
return null;
}
public Void invokeSoapApi() {
//soap api call
return null;
}
请注意,线程池应在应用程序启动时创建。 所以如果你真的想使用它,那么你应该将“executorService”定义为实例变量。例如
@Service
public class MyService {
...
...
private ExecutorService executorService = Executors.newFixedThreadPool(2);
...
...
//your methods
}
这是 CompletableFuture
的预期行为,如果您查看它说的文档 -
/**
* Returns a new CompletableFuture that is asynchronously completed
* by a task running in the ForkJoinPool#commonPool() after
* it runs the given action.
*
* @param runnable the action to run before completing the
* returned CompletableFuture
* @return the new CompletableFuture
*/
你可以使用阻塞Future.get()来实现你想要的(如下图)
void deleteSomething(){
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Void> future = executorService.submit(() -> {
invoke("Invoking soap API");
return null;
});
//some other code
future.get();
}
不建议在方法中创建线程池,因为线程创建会产生开销。理想情况下,应在应用程序启动时创建线程池。