1

I have googled and found the best way to use multithreading but its failing for a 100 records it giving 504 status code. Is there any scope to improve the below code?

@Scheduled(fixedRate = 5000)
public ResponseEntity<Object> getData(List<JSONObject> getQuoteJson, String username,
                                      String authorization) throws ParseException, IOException, Exception {
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set("Access-Control-Allow-Origin", "*");
    CompletableFuture<JSONArray> future = null;
    JSONArray responseArray = new JSONArray();
    try {
        executor = Executors.newFixedThreadPool(getQuoteJson.size());
        for (int i = 0; i < getQuoteJson.size(); i++) {
            JSONObject jsonObject = (JSONObject) getQuoteJson.get(i);
            future = CompletableFuture.supplyAsync(() -> {
                JSONObject response = asynCallService.getDataAsyncService(jsonObject, productCode, authorization);
                responseArray.add(response);
                return responseArray;
            }, executor);
        }
        return new ResponseEntity<Object>(future.get(), responseHeaders, HttpStatus.OK);
    } catch (Exception e) {
        throw e;
    } finally {
        executor.shutdown();
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (Exception e) {
        }
    }

}
xingbin
  • 27,410
  • 9
  • 53
  • 103
  • 3
    On a sidenote: "I have [...] found the best way to use multithreading" is a statement I would be quite cautious with. There is no best way to use multithreading. More often than not there isn't even a clear "best way" for a specific use-case. – Ben Sep 04 '18 at 10:34
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504 for the unititiated – Brian Agnew Sep 04 '18 at 10:37
  • Given that 504 relates to a *gateway*, is that coming from a service you're calling from within your multithreaded code? – Brian Agnew Sep 04 '18 at 10:52
  • `responseArray.add(response);` is probably not thread safe to use inside a future's body. – GPI Sep 04 '18 at 11:48

2 Answers2

3

Do not create and shutdown executor every time, use a singleton cached thread pool. Since creating threads repeatly is unecessary and expensive, and the benefit of thread pool is keeping threads existing.

xingbin
  • 27,410
  • 9
  • 53
  • 103
  • Hi Sun, can you please help a bit deeper? –  Sep 04 '18 at 10:38
  • @Soham Please check the link in the answer. Creating thread is expensive, you can use cached thread pool to avoid it. So you do not need create `executor = Executors.newFixedThreadPool(getQuoteJson.size());` every time. You can just hold a global executor. – xingbin Sep 04 '18 at 13:52
1

Wow all of this to iterate asynchronly on a list ?

this is i think more likely to be what you searched :

HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Access-Control-Allow-Origin", "*");
final JSONArray responseArray = new JSONArray();
getQuoteJson.parallelStream().map(e->asynCallService.getDataAsyncService(e, productCode, authorization)).forEach(responseArray::add);
return new ResponseEntity<Object>(responseArray, responseHeaders, HttpStatus.OK);