Java Future: get the time per request - java

I have a piece of code that needs to make 15 requests in parallel then wait for all the requests to complete before proceeding.
Each request takes somewhere between 500-2500 ms. Is there a way in Java to get the time it takes for each future to complete the request?

I don't know of any built in methods in the Future api itself. However, if you use ListenableFutures, you can start a timer when you make the future and and stop the timer in the onSuccess or onFailure callback. Concretely, this could look something like:
public void timeRequests(MyRequests[] requestsToMake) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(requestsToMake.length));
long startTimeNanos = System.nanoTime();
long[] endTimes= new long[requestsToMake.length]
for(int i =0; i < requestsToMake.length; i++){
MyRequest req = requestsToMake[i];
ListenableFuture<MyData> rFuture = service.submit(new Callable<MyRequest>() {
public MyData call() {
return req.makeRequest();
}
});
Futures.addCallback(rFuture, new FutureCallback<MyData>() {
public void onSuccess(MyData data) {
endTimes[i]=System.nanoTime();
//whatever else you do
}
public void onFailure(Throwable thrown) {
endTimes[i]=System.nanoTime();
//whatever else you do
}
});
}

Related

JAX-RS API Leaking Threads

I have the following code:
public static Client client = ClientBuilder.newClient();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.activeCount());
client.target("https://en.wikipedia.org/wiki/Special:Random").request().buildGet().submit(new InvocationCallback<Response>() {
#Override
public void completed(Response response) {
response.close();
}
#Override
public void failed(Throwable throwable) {
}
});
}
Thread.sleep(10000L);
System.out.println(Thread.activeCount());
}
Each time I call .submit() the client creates a new thread for the new get request that just permanently stays open. The problem with this is that I eventually reach the max # of threads and the program malfunctions because it cannot create a new thread. How do I avoid this problem?
Output:
1
2
3
4
...
101
The ideal solution would be to make this program single threaded and hang the program until each get-request receives a response. I'm open to using an alternative API if this is not possible with javax.ws.rs.

How to wait for callback to finish before continuing the loop?

I'm trying to add restMedia to restaurantMediaList in onResponse within a for loop. However, when the loop is finished, restaurantMediaList is null. How can I fix this in such a way that it waits for onResponse to be finished first before proceeding with the next iteration?
public void getImages(List<Restaurant> restaurantList, OnImageReceivedCallback callback){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
WordpressAPICall wordpressAPICall = retrofit.create(WordpressAPICall.class);
for(int i = 0; i < restaurantList.size(); i++){
String featuredMediaURL = restaurantList.get(i).get_links().getFeaturedMedia().get(0).getHref();
featuredMediaURL.substring(featuredMediaURL.indexOf("v2")+1);
Call<RestaurantMedia> restMediaCall = wordpressAPICall.getImage(featuredMediaURL);
restMediaCall.enqueue(new Callback<RestaurantMedia>() {
#Override
public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
RestaurantMedia restMedia = response.body();
restaurantMediaList.add(restMedia);
//callback.onRestaurantListReceived(restaurantModels, restMedia);
}
#Override
public void onFailure(Call<RestaurantMedia> call, Throwable t) {
Log.d("Fail to get media", t.toString());
}
});
}
callback.onImageReceived(restaurantMediaList);
}
Keep in mind that there are restaurantList.size() different threads (each fires a network request) and the only choice you have is to use some lock.
If there is an API that fetches all of the images together please use it and use my 1st code to wait for result.
I also recommend using timeout because if, for some reason, onResponse AND onFailure will not be called, your calling thread will sleep forever. Tweak the timeout as you see fit.
Waiting for each thread to finish separately is extremely time consuming so I'd recommend to let them go asynchronous and continue when all of them are done.
I'll show you both options.
Wait for each one to wait separately:
CountDownLatch countDownLatch = new CountDownLatch(1);
restMediaCall.enqueue(new Callback<RestaurantMedia>() {
#Override
public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
// Do your thing
countDownLatch.countDown();
}
#Override
public void onFailure(Call<RestaurantMedia> call, Throwable t) {
// Do your thing
countDownLatch.countDown();
}
});
countDownLatch.await(1L, TimeUnit.SECONDS); // join thread with timeout of second
Waiting for all threads together:
public void getImages(List<Restaurant> restaurantList, OnImageReceivedCallback callback){
// Do your thing
CountDownLatch countDownLatch = new CountDownLatch(restaurantList.size());
for(int i = 0; i < restaurantList.size(); i++){
// Do your thing
restMediaCall.enqueue(new Callback<RestaurantMedia>() {
#Override
public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
// Do your thing
countDownLatch.countDown();
}
#Override
public void onFailure(Call<RestaurantMedia> call, Throwable t) {
// Do your thing
countDownLatch.countDown();
}
});
}
countDownLatch.await(1L * restaurantList.size(), TimeUnit.SECONDS); // join thread with timeout of second for each item
}

Measure execution time of async method

I have async method where I use DeferredResult as return type. I want write junit test for that method where I call this method in loop, e.g 100 times, and I need measure execution time for every call of that method.
Here is method sample:
#Transactional(readOnly = true)
#Override
public DeferredResult foo() {
DeferredResult dr = new DeferredResult(5000L, "timeout");
dr.onCompletion(() -> {
// do some stuff
});
deferredResults.add(dr);
return dr;
}
created deferredResult I add into collection, and I iterate that collection in another method where I set some result, and then is dr returned.
Can you show my how should looks like test where I will be able measure execution time of multiple calls of that method?
#Test
public void executionTimeTest() {
for (int i = 0; i < 100; i++) {
asyncService.foo();
}
// here I need get execution time for each call
}
Thanks.
I think the best way to solve this question is adding additional data in DeferredResult class as it is recommended by spring docs. Precisely, the following sentence in spring docs points out this possibility.
Subclasses can extend this class to easily associate additional data
or behavior with the DeferredResult. For example, one might want to
associate the user used to create the DeferredResult by extending the
class and adding an additional property for the user. In this way, the
user could easily be accessed later without the need to use a data
structure to do the mapping.
Given this possibility, you can extend the DeferredResult and add a start and end time:
public class MyDeferredResult extends DeferredResult {
long startTime;
long endTime;
public MyDeferredResult(Long timeout, Object timeoutResult) {
super(timeout, timeoutResult);
this.startTime = System.currentTimeMillis();
}
#Override
public boolean setResult(Object result) {
boolean r = super.setResult(result);
this.endTime = System.currentTimeMillis();
return r;
}
public long totalTime() {
return (endTime - startTime)/1000;
}
}
Then, your Async Service can be similar to this one:
public MyDeferredResult foo() {
MyDeferredResult dr = new MyDeferredResult(5000L, "timeout");
new Thread(() -> {
Random r = new Random();
System.out.println("async task started");
try {
Thread.sleep(r.nextInt(4) * 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("async task finished");
dr.setResult("test async result");
}).start();
deferredResults.add(dr);
return dr;
}
boolean hasResults() {
boolean result = true;
for(MyDeferredResult dr: deferredResults) {
result = result && dr.hasResult();
}
return result;
}
Finally, in your test, you can retrieve the total time of each execution:
#Test
public void executionTimeTest() {
Service service = new Service();
for (int i = 0; i < 10; i++) {
service.foo();
}
while (!service.hasResults()) {
System.out.println("No result yet");
}
for(MyDeferredResult dr: service.deferredResults) {
System.out.println(dr.totalTime());
}
}

Calling mutiple webservice at same time in Spring Java

I have a list of 30 servers and I have to make a REST call to each server to get their status. Currently I iterating through list of server and sequentially calling each REST call against each server. So totally it takes around 30 seconds in total to get the response from each server before returning the result to JSP VIEW.
How can we improve this?
One option you could consider is the Java8 streams like:
public void check() {
List<String> endPoints = Arrays.asList("http://www.google.com", "http://www.stackoverflow.com", "inexistent");
{
// this will execute the requests in parallel
List<Boolean> collected = performCheckOverStream(endPoints.parallelStream());
System.out.println(collected);
}
{
// this will execute the requests in serial
List<Boolean> collected = performCheckOverStream(endPoints.stream());
System.out.println(collected);
}
}
private List<Boolean> performCheckOverStream(Stream<String> stream) {
List<Boolean> collected = stream.map(new Function<String, Boolean>() {
#Override
public Boolean apply(String t) {
// do what you need here
}
}).collect(Collectors.toList());
return collected;
}
Using Spring you could either use a #Async annotated method or even use the AsyncRestTemplate, in both cases you will receive a Future<?>. A nice introduction to #Async can be found here and to the AsyncRestTemplate here.
You can do it via ThreaPool like this , with Thread count as your API call count.
public void REST_Thread_executor(int Thread_count, ArrayList URLS) {
ExecutorService executor = Executors.newFixedThreadPool(Thread_count);
for (int i = 0; i < Thread_count; i++) {
String URL = URLS.get(i).toString();
Runnable worker = new MyRunnable(URL);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
}
public String restAPICALL(URL) {
GET or POST or PUT or DELETE
}
public static class MyRunnable implements Runnable {
private final String URL;
RESTThreadExecutor restThreadExecutor = new RESTThreadExecutor();
MyRunnable(String URL) {
this.URL = URL;
}
#Override
public void run() {
restThreadExecutor.restAPICALL(URL);
}
}
You can use the CompletableFuture Interface from java 9. Or the enable on your app the #EnableAsync and on your method use the #Async that will return to you an interface Future.
The both are asynchronous stream.

Java multithreaded programming using with Guava FutureCallback interface

My question is related to java multithreaded programming.
I am dealing with main thread that creates many workers, every worker is a thread.
To get results/errors from workers to main thread i used with Callable and Future.
I did find in guava FutureCallback interface to get exceptions from worker.
My question is how to use it, because I didn't find any examples on the web.
Thanks !
Here is an example with Integer results:
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(4));
int runs = 100;
for (int k=0; k < runs; k++) {
Callable<Integer> job = ...; // create the job here
ListenableFuture<Integer> completion = executor.submit(job);
Futures.addCallback(completion, new FutureCallback<Integer>() {
#Override
public void onFailure(Throwable t) {
// log error
}
#Override
public void onSuccess(Integer result) {
// do something with the result
}
});
}
executor.shutdown();
while (!executor.isTerminated()) {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}

Categories