Java两个Web服务调用会同时实现更好的性能

时间:2014-03-07 11:26:13

标签: java multithreading performance concurrent-programming

在我的付款处理服务中,我有两个不同的网络服务电话。 首先打电话获取客户的详细信息,然后再拨打支付网关服务进行支付处理。 这些调用不依赖于彼此,可以按任何顺序调用。

支付网关呼叫配置为30秒超时和客户详细信息呼叫10秒。目前同步调用它们需要40秒(30 + 10)。

出于性能原因,我希望异步调用这些调用。异步调用它们将节省10秒的处理时间,因为支付网关正在处理对客户详细信息的并发呼叫时,可以同时完成。

如何在java中优雅地实现它?

4 个答案:

答案 0 :(得分:2)

这就是我做的事情

try {
    // Create Future task of type CustomerDetail
    FutureTask<CustomerDetail> customerDetailTask = new FutureTask<CustomerDetail>(
        @SuppressWarnings({ "unchecked", "rawtypes" })
        new Callable() {
            @Override
            public CustomerDetail call() throws Exception {
                return customerDetailService.getCustomerDetail(customerId);
            }
        }
    );


    // Create Future task of type PaymentResponse           
    FutureTask<PaymentResponse> paymentProcessingTask = new FutureTask<PaymentResponse>(
        @SuppressWarnings({ "unchecked", "rawtypes" })
        new Callable() {
            @Override
            public PaymentResponse call() throws Exception {
                return paymentProcessingService.processPayment(paymentRequest);
            }
        }
    );

    // Call two tasks asynchronously
    callAsynchronously(customerDetailTask, paymentProcessingTask);

catch (Exception e) {
    log.error(e);
}


private PaymentResponse callAsynchronously(FutureTask<CustomerDetail> customerDetailTask, FutureTask<PaymentResponse> paymentTask) throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    if (customerDetailTask != null) {
        executor.execute(customerDetailTask);
    }
    executor.execute(paymentTask);

    while (true) {
        if (paymentTask.isDone()) {
            log.info("Payment task done.");
            PaymentResponse payResponse = paymentTask.get();
            if (customerDetailTask != null ) {
                if ( customerDetailTask.isDone() ) {
                    log.info("Customer detail task done.");
                    payResponse.setCustomerDetail(customerDetailTask.get());
                    return payResponse;
                }
            } else {
                log.info("Payment without Customer detail task.");
                return payResponse;
            }
        }
    }
}

答案 1 :(得分:1)

您可以查看用于创建并发网络服务的各种框架。首先,自3.0以来的servlet具有异步API(http://www.javaworld.com/article/2077995/java-concurrency/asynchronous-processing-support-in-servlet-3-0.html)。第二种选择是使用更专业的框架,例如Akka

答案 2 :(得分:1)

例如,您可以使用ExecutorService + Callable执行此操作。

创建两个实现Callable接口的类,创建执行器服务,添加两个服务任务并获取功能。从期货获得通话结果。

答案 3 :(得分:0)

Count Down Latch

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。

样本用法:

这是一对类,其中一组工作线程使用两个倒计时锁存器:

  • 第一个是启动信号,阻止任何工人继续行动,直到司机准备好让他们继续;
  • 第二个是完成信号,允许驾驶员等到所有工人都完成。

代码:

class Driver { // ...
    void main() throws InterruptedException {
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(N);

        for (int i = 0; i < N; ++i)
            // create and start threads
            new Thread(new Worker(startSignal, doneSignal)).start();

        doSomethingElse(); // don't let run yet
        startSignal.countDown(); // let all threads proceed
        doSomethingElse();
        doneSignal.await(); // wait for all to finish
    }
}

class Worker implements Runnable {
    private final CountDownLatch startSignal;
    private final CountDownLatch doneSignal;

    Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
        this.startSignal = startSignal;
        this.doneSignal = doneSignal;
    }

    public void run() {
        try {
            startSignal.await();
            doWork();
            doneSignal.countDown();
        } catch (InterruptedException ex) {
        } // return;
    }

    void doWork() { ... }
}