Hi, There,
I think you already know about the Asynchronous and Synchronous calls in JAVA. If not, the basic definition of sync, and async call as below,
Synchronous, The code execution will block or wait for the event before continuing. Until your event returns a response, your program will not execute any further.
Asynchronous, An Asynchronous call does not block the program from the code execution. When the call returns from the event, the call returns back to the callback function.
There are so many benefits of using Async call, In this example, I am just demonstrating for the time performance.
Below is the example of Synchronous VS Asynchronous with the time difference, This will determine why should we go for Asynchronous.
Here I’m using JAVA 8 JDK and the Jackson library to convert JSON to JAVA Object.
Let’s being in REAL,
Step 1) First create the DummyEmployeeDto class,
import java.io.Serializable;
public class DummyEmployeeDto implements Serializable {
private static final long serialVersionUID = 1L;
private String id, employee_name, employee_salary, employee_age,
profile_image;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmployee_name() {
return employee_name;
}
public void setEmployee_name(String employee_name) {
this.employee_name = employee_name;
}
public String getEmployee_salary() {
return employee_salary;
}
public void setEmployee_salary(String employee_salary) {
this.employee_salary = employee_salary;
}
public String getEmployee_age() {
return employee_age;
}
public void setEmployee_age(String employee_age) {
this.employee_age = employee_age;
}
public String getProfile_image() {
return profile_image;
}
public void setProfile_image(String profile_image) {
this.profile_image = profile_image;
}
}
Step 2) Create the AsyncCall class where we will Execute our calls,
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class AsyncCall {
//increase to make faster. Multiply a few times to melt server.
private static final int MAX_THREADS = 10;
private static final long TIME_OUT = 180;
public <c> List<c> callAsync(final List<Callable<c>> calls) {
return callAsync(calls, TIME_OUT);
}
private <c> List<c> callAsync(List<Callable<c>> callsToMake, long timeOut) {
List<c> output = new ArrayList<>();
int threadCount = (callsToMake.size() > MAX_THREADS) ? MAX_THREADS : callsToMake.size();
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
try {
executorService.invokeAll(callsToMake).forEach(cFuture -> {
try {
output.add(cFuture.get(timeOut, TimeUnit.SECONDS));
} catch (ExecutionException | TimeoutException | InterruptedException e) {
e.printStackTrace();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
return output;
}
}
Step 3) Add Codehaus Jackson Core and Mapper from the following link to your project,
https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl
https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl
Step 4) Create a HttpurlConnection class, where we will call the dummy URL, get a response and convert JSON to DummyEmployeeDto class.
import org.codehaus.jackson.map.ObjectMapper;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class HttpurlConnection {
private ObjectMapper mapper = new ObjectMapper();
public static String getResponse(String url, String method, String header, String body) {
StringBuilder builder = new StringBuilder();
try {
URL url1 = new URL(url);
HttpURLConnection con = (HttpURLConnection) url1.openConnection();
con.setRequestMethod(method);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
builder.append(inputLine);
}
in.close();
con.disconnect();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return builder.toString();
}
public <T> List<T> getResponseData(T clazz, String url, String method) {
List<T> returnObjectList = new ArrayList<>();
try {
String response = HttpurlConnection.getResponse(url, method, "", "");
String reponseData = response.split("data\":")[1].split("]}")[0] + "]";
returnObjectList = mapper.readValue(reponseData, mapper.getTypeFactory().constructCollectionType(List.class, DummyEmployeeDto.class));
} catch (Exception e) {
e.printStackTrace();
}
return returnObjectList;
}
}
Step 5) Finally create the AsyncCallExample Main class and run,
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class AsyncCallExample {
private static DummyEmployeeDto employeeDto = new DummyEmployeeDto();
private static String dummyUrl = "http://dummy.restapiexample.com/api/v1/employees";
private static AsyncCall asyncCall = new AsyncCall();
public static void main(String[] args) {
Long start;
Long end;
// with out async Regular
HttpurlConnection connection = new HttpurlConnection();
start = System.currentTimeMillis();
List<DummyEmployeeDto> listData = connection.getResponseData(employeeDto, dummyUrl, "GET");
List<DummyEmployeeDto> listData1 = connection.getResponseData(employeeDto, dummyUrl, "GET");
List<DummyEmployeeDto> listData3 = connection.getResponseData(employeeDto, dummyUrl, "GET");
List<DummyEmployeeDto> listData4 = connection.getResponseData(employeeDto, dummyUrl, "GET");
listData.addAll(listData1);
listData.addAll(listData3);
listData.addAll(listData4);
end = System.currentTimeMillis();
System.out.println("Total time taken with out async call in ms -->>> : " +(end - start));
System.out.println("total data size " + listData.size());
// with async
start = System.currentTimeMillis();
List<Callable<List<DummyEmployeeDto>>> calls = new ArrayList<>();
calls.add(() -> connection.getResponseData(employeeDto, dummyUrl, "GET"));
calls.add(() -> connection.getResponseData(employeeDto, dummyUrl, "GET"));
calls.add(() -> connection.getResponseData(employeeDto, dummyUrl, "GET"));
calls.add(() -> connection.getResponseData(employeeDto, dummyUrl, "GET"));
List<List<DummyEmployeeDto>> lists = asyncCall.callAsync(calls);
final AtomicInteger count = new AtomicInteger();
listData = lists.stream()
.flatMap(List::stream)
.peek(data -> data.setId(String.valueOf(count.incrementAndGet())))
.collect(Collectors.toList());
end = System.currentTimeMillis();
System.out.println("Total time taken with async call in ms ----->>> : " +(end - start));
System.out.println("total data size " + listData.size());
}
}
Once we run the main class we will see the following result,
Finally, We all see the difference by calling with Async way and sync way. This is the only for the example and having a simple connection.
Async calls help to improve performance.
In this example For the regular call, when the first getResponseData method is calling then others call are waiting for execution. Once the first method is completed then only the second method will executes and other methods will wait to complete and it goes the same way for others. Hence it takes more time.
On the other hand for the Async call, all the method calls are independent of each other and it executes parallelly.
If you have any comments/Questions, Fell free to add in the comment section below.