For example, you can do this with ExecutorService + Callable.
Make two classes that implements Callable interface, create executor service, add two tasks to service and get features. From futures get result of calls.
Question
In my payment processing service I have two different webservice calls. First call to get customer's details and second call to payment gateway service for payment processing. These calls are not dependant on each other and can be called in any order.
Payment gateway call configured with 30 seconds timeout and customer detail call with 10 seconds. Currently calling them synchronously takes 40 seconds (30 + 10).
I want these calls to be made asynchronously for the performance reason. Calling them asynchronously will save 10 seconds processing as when payment gateway is processing the concurrent call to the customer details could be completed in the mean time.
How to implement this in java elegantly?
La solution 2
For example, you can do this with ExecutorService + Callable.
Make two classes that implements Callable interface, create executor service, add two tasks to service and get features. From futures get result of calls.
Autres conseils
This is what I did
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;
}
}
}
}
You may take a look at various frameworks for creating concurrent networks services. First of all servlets since 3.0 have asynchronous API ( http://www.javaworld.com/article/2077995/java-concurrency/asynchronous-processing-support-in-servlet-3-0.html ). The second option is to use a more specialized framework like for example Akka
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Here is a pair of classes in which a group of worker threads use two countdown latches:
Code:
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() { ... }
}