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.
CodePudding user response:
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.