Home > Software design >  Java Concurrent Executor Service returning inconsistent responses
Java Concurrent Executor Service returning inconsistent responses

Time:08-03

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.

  • Related