threw out all unnecessary from the code:

@RestController @Scope("prototype") public class Test { private static List<DiOr> deliveryOrderList; private static List<TK> objList; private static ExecutorService executor; public Test() { objList = new ArrayList<TK>(); objList.add(new Obj1()); objList.add(new Obj2()); // неизвестно сколько может быть ... executor = Executors.newFixedThreadPool(objList.size()); } @RequestMapping(value = "/test", method = RequestMethod.GET, produces = "application/json;charset=UTF-8") public synchronized static List<DiOr> getTest() { deliveryOrderList = new ArrayList<>(); objList.stream().forEach((s) -> { final TK finalS = s; executor.submit(() -> { deliveryOrderList.add(finalS.get()); }); }); executor.shutdown(); executor.awaitTermination(2, TimeUnit.MINUTES); return deliveryOrderList; } } 

In the end, I want to achieve that when accessing URL / test, objects created in the constructor run one method (each method runs at different times) in a separate thread of someone or the pool. after completion of execution of all threads of the pool, the method returned some json (there are no problems here).

Since the returned object is static, if you remove synchronized static - if you simultaneously request to the URL more than once, incorrect data will be returned, some method will work, some will not have time, and so on.

When I finish synchronized static (as in the example) everything is done correctly, but as I understand it, a queue is formed for executing these pools ... and if you simultaneously query this URL, the running time increases significantly, for those who are in this queue . For me, this is critical ...

How best to solve this problem?

  • The problem you want to solve is not completely clear. It is better to describe how it should work, and as already implemented with a minimal example. - MrFylypenko
  • Now I will try to describe in more detail - igor
  • If you optimize the getTest () method, then you can win well. finalS.get() what does? forEach() needs to be replaced by parallelStram().map() - Senior Pomidor
  • finalS.get () - api fires requests to third-party servers and returns their response. Thanks for parallelStram, now I will try ... speed is important in this case - igor
  • I would recommend deliveryOrderList to make synchronized volatile to add data in different streams, and synchronize to parallelize finalS.get () - Senior Pomidor

1 answer 1

If you want your code to work quickly, then in no case can you synchronize the controller. So you turn your service into a single-threaded one, capable of processing only one request at a time.

In spring e, rarely you have to explicitly create a thread pool, and this is not your case. If you really want to, then you can indulge in the @Async annotation.

From your question, it is not clear why creating a shared static field. It is completely possible to do without it:

 @RestController public class Test { private static List<TK> objList; @PostConstruct public void setup() { objList = new ArrayList<TK>(); objList.add(new Obj1()); objList.add(new Obj2()); // неизвестно сколько может быть ... } @RequestMapping(value = "/test", method = RequestMethod.GET, produces = "application/json;charset=UTF-8") public List<DiQr>getTest() { List<DiOr> deliveryOrderList = new ArrayList<DiQr>(); objList .parallelStream() .forEach((s) -> { deliveryOrderList.add(s.get()); }); return deliveryOrderList; } }