java – 在Spring 4中运行并行线程的优雅方式

我正在开发一个API.此API需要执行2次DB查询才能获得结果.

我尝试了以下策略:

>在Controller中使用可调用作为返回类型.

>在Service中创建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中获取数据的最有效方法是什么.

– 如何知道运行自己查询的2个线程完成了他们的工作?

– 如何控制线程资源,如使用和释放线程?

提前致谢.

解决方法:

您通常不希望在ApplicationServer中创建自己的线程,也不想管理线程生命周期.在应用程序服务器中,您可以将任务提交到ExecutorService以池化后台工作线程.

方便的是,Spring有@Async注释,可以为您处理所有这些.在您的示例中,您将创建两个返回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);
    }
}

只要您配置ThreadPoolTask​​Executor并启用异步方法,Spring就会处理为您提交任务的过程.

注意:get()方法阻塞当前线程,直到工作线程返回结果,但不阻止其他工作线程.通常建议设置超时以防止永久阻塞.

上一篇:异步查询转同步加redis业务实现的BUG分享


下一篇:Java 并发工具类 CountDownLatch、CyclicBarrier、Semaphore、Exchanger