我正在开发一个 API。此 API 需要执行 2 次数据库查询才能获得结果。
我尝试了以下策略:
- 在 Controller 中使用 callable 作为返回类型。
在服务中创建了 2 个线程(使用 Callable 和 CoundownLatch)来并行运行 2 个查询并检测完成时间。
public class PetService { public Object getData() { CountDownLatch latch = new CountDownLatch(2); AsyncQueryDBTask<Integer> firstQuery= new AsyncQueryDBTask<>(latch); AsyncQueryDBTask<Integer> secondQuery= new AsyncQueryDBTask<>(latch); latch.await(); } public class AsyncQueryDBTask<T> implements Callable { private CountDownLatch latch; public AsyncQueryDBTask(CountDownLatch latch) { this.latch = latch;} @Override public T call() throws Exception { //Run query latch.countDown(); }
它工作得很好,但我觉得我在某处破坏了 Spring 的结构。
我想知道在 Spring 4 中获取数据最有效的方法是什么。
-如何知道运行自己的查询的两个线程都完成了他们的工作?
-如何控制线程资源,如线程的使用和释放?
提前致谢。
最佳答案
您通常不想在 ApplicationServer 中创建自己的线程,也不想管理线程生命周期。在应用程序服务器中,您可以将任务提交到 ExecutorService
以汇集后台工作线程。
方便的是,Spring 有一个@Async
注释可以为您处理所有这些。在您的示例中,您将创建 2 个返回 Future 的异步方法:
public class PetService {
public Object getData() {
Future<Integer> futureFirstResult = runFirstQuery();
Future<Integer> futureSecondResult = runSecondQuery();
Integer firstResult = futureFirstResult.get();
Integer secondResult = futureSecondResult.get();
}
@Async
public Future<Integer> runFirstQuery() {
//do query
return new AsyncResult<>(result);
}
@Async
public Future<Integer> runSecondQuery() {
//do query
return new AsyncResult<>(result);
}
}
只要您配置一个ThreadPoolTaskExecutor
并启用异步方法,Spring 就会为您处理提交任务。
注意:get()
方法会阻塞当前线程,直到工作线程返回结果,但不会阻塞其他工作线程。通常建议设置超时以防止永远阻塞。
关于java - 在 Spring 4 中运行并行线程的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41971999/