Here, I have configured a scheduler, which will trigger the function after the application startup. Within the scheduler, the WHILE loop is supposed to iterate infinitely and capture responses until encountered an error.
Application Entry Point
@Service
public class Application {
@Autowired
MyService service;
@Scheduled(initialDelay = 1000, fixedDelay = 30000)
public void init() {
while (true) {
try {
String[] alphabets = {"a","b","c","d","e"};
List < String > response = service.getResult(Arrays.asList(alphabets));
system.out.println(response);
} catch (CustomExceptionMan e) {
throw new CustomException(...);
}
}
}
}
Logic
@Service
public class MyService {
public List < String > getResult(List < String > alphabets) {
List < String > response = new ArrayList < > ();
ExecutorService executor = Executors.newFixedThreadPool(10);
List < Future << ? >> futures = new ArrayList < > ();
alphabets.forEach(alpha - > {
futures.add(executor.submit(new Runnable() {
@Override
public void run() {
try {
apiCall(alpha, response);
} catch (Exception e) {
throw new CustomException(...);
}
}
}));
});
executor.shutdown();
futures.forEach(i - > {
try {
i.get(10000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new CustomException(....);
}
});
// Even Tried this
while (!executor.isTerminated()) {}
return response;
}
public void apiCall(String alpha, List < String > response) {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {}
response.add(alpha.toUpperCase());
}
}
Output once the scheduler start:-
1st iteration response: [E, A, D, C, B]
2nd iteration response: [A, D, E]
3rd iteration response: [A, C, D, E]
4th iteration response: [A, B, C, D, E]
so on....
Why isn't the response size consistent?
In all iterations, I expect the size to be same i.e. 5. My understanding is, future.get(...) will block the code flow until the task execution is completed.
Multiple threads are writing to same response, use thread-safe writes, you could use CopyOnWriteArrayList
instead:
List < String > response = new CopyOnWriteArrayList<>();
Calling Future.get(long timeout, TimeUnit unit)
may not leave enough time for all tasks is complete, try using Future.get()
instead or use ExecutorService.awaitTermination(long timeout, TimeUnit unit)
on a executor service at the end rather than relying on while loop to see if tasks are ended.