4


我正在开发一个 API。此 API 需要执行 2 次 DB 查询才能获得结果。
我尝试了以下策略:

  • 在 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 中获取数据的最有效方法是什么
。-如何知道运行自己的查询的两个线程都完成了工作?
-如何控制线程资源的使用和释放?

提前致谢。

4

1 回答 1

8

您通常不想在 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()方法会阻塞当前线程,直到工作线程返回结果,但不会阻塞其他工作线程。通常建议设置超时以防止永远阻塞。

于 2017-02-01T06:06:21.667 回答