2

I'm trying to execute some parallel methods inside my controller but i'm having a few problems with the return type.

I have 4 methods and each of those methods return a list.I need to execute those methods in a parallel way and then get each returned list and place all of those lists inside a map and return that map from the controller. Here's the code:

Callable<List> callable1 = new Callable<List>()
           {
              @Override
              public List call() throws Exception
              {
                List<SearchResultAutovit> lista;
                lista = scrapperAutovit.searchAutovit(marcaId, modelId, pretDeLa, pretPanaLa, anFabrDeLa, anFabrPanaLa,
                        orasParam);
                 return lista;
              }
           };

           Callable<List> callable2 = new Callable<List>()
           {
              @Override
              public List call() throws Exception
              {
                  List<SearchResultOlx> listaOlx;
                String marcaOlx = marcaId.toLowerCase();
                String modelOlx = modelId.toLowerCase();
                String orasOlx = orasParam.toLowerCase();
                listaOlx = scrapperOlx.searchOlx(marcaOlx, modelOlx, pretDeLa, pretPanaLa, anFabrDeLa, anFabrPanaLa, orasOlx);
                 return listaOlx;
              }
           };

           Callable<List> callable3 = new Callable<List>()
           {
              @Override
              public List call() throws Exception
              {
                List<SearchResultPubli24> listaPubli24;
                String orasPubli24 = orasParam.toLowerCase();
                listaPubli24 = scrapperPubli24.searchPubli24(marcaId, modelId, orasPubli24, anFabrDeLa, anFabrPanaLa, pretDeLa, pretPanaLa);
                 return listaPubli24;
              }
           };

           Callable<List> callable4 = new Callable<List>()
           {
              @Override
              public List call() throws Exception
              {
                 List<SearchResultAutoUncle> listaAutoUncle;
                listaAutoUncle = scrapperAutoUncle.searchAutoUncle(marcaId, modelId, pretDeLa, pretPanaLa, anFabrDeLa, anFabrPanaLa, orasParam);
                 return listaAutoUncle;
              }
           };

           //add to a list
           List<Callable<List>> taskList = new ArrayList<Callable<List>>();
           taskList.add(callable1);
           taskList.add(callable2);
           taskList.add(callable3);
           taskList.add(callable4);

           ExecutorService executor = Executors.newFixedThreadPool(3);
           executor.invokeAll(taskList);

           Map<String,List<?>> listOfWebsites = new HashMap<>();
            listOfWebsites.put("listaAutovit", (List<?>) taskList.get(0));
            listOfWebsites.put("listaOlx", (List<?>) taskList.get(1));
            listOfWebsites.put("listaPubli24", (List<?>) taskList.get(2));
            listOfWebsites.put("listaAutoUncle", (List<?>) taskList.get(3));

        return listOfWebsites;

I'm pretty sure that i'm not doing something right because it throws java.lang.ClassCastException: com.test.controller.HomeController$1 incompatible with java.util.List I guess the problem is the map called listOfWebsites which should have the returned type of the callables, some lists:(

4
  • What do you mean? This code is not inside the constructor Commented Nov 18, 2018 at 13:59
  • Sorry, misread the question. I'm in a noisy room. I'll remove my comment. Commented Nov 18, 2018 at 14:10
  • Hint HomeController$1 is your Callable... More generally though, you should plan to do the whole process asynchronously and return a Future from your controller method. Commented Nov 18, 2018 at 14:10
  • Also - all your lists are rawtypes... Commented Nov 18, 2018 at 14:21

2 Answers 2

4

First, change type of callables to avoid casting:

    Callable<List<?>> callable1 = new Callable<List>(){...}

Then, you have to wait for results of parallel computations. You need not to create CompletableFutures because you can obtain Futures directly from ExecutorService:

    ExecutorService executor = Executors.newFixedThreadPool(3);
    Future<List<?>> future1 = executor.submit(callable1);
    Future<List<?>> future2 = executor.submit(callable2);
    Future<List<?>> future3 = executor.submit(callable3);
    Future<List<?>> future4 = executor.submit(callable4);

    Map<String,List<?>> listOfWebsites = new HashMap<>();
    listOfWebsites.put("listaAutovit", future1.get());
    listOfWebsites.put("listaOlx", future2.get());
    listOfWebsites.put("listaPubli24", future3.get());
    listOfWebsites.put("listaAutoUncle", future4.get());

    return listOfWebsites;

That's it.

Sign up to request clarification or add additional context in comments.

Comments

1

I would suggest to use completableFuture Object with supplyasync method. Giving you approach like below:

CompletableFuture<String> completableFuture
  = CompletableFuture.supplyAsync(() -> scrapperAutovit.searchAutovit);

CompletableFuture<String> completableFuture1
  = CompletableFuture.supplyAsync(() -> scrapperOlx.searchOlxwith);

CompletableFuture<String> completableFuture2
  = CompletableFuture.supplyAsync(() -> scrapperPubli24.searchPubli24);

would be used to check whether you got some response from above call or not.

Like that you can open parallel thread for scrapperOlx.searchOlxwith and scrapperPubli24.searchPubli24 completableFuture object and wait for execution to finish there task and after that consolidate all data and you can process further.

For more details you can refer below link https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html https://dzone.com/articles/java-8-definitive-guide https://www.callicoder.com/java-8-completablefuture-tutorial/

This is the good example to understand completablefuture Multiple thenApply in a completableFuture

4 Comments

I'm not sure i understand:( where should i use this CompletableFuture?
all future object which you have created in callable can use by completablefuture like i have mentioned one example for scrapperAutovit.searchAutovit like you can parallel y run with scrapperOlx.searchOlx this as so on i have also shared few link you just go through this link you will understand its a java8 future object.
Note this will use the common pool rather than a custom executor.
You can provide the custom executor as well through constructor.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) { return asyncSupplyStage(screenExecutor(executor), supplier); }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.