Reputation: 539
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:(
Upvotes: 2
Views: 5529
Reputation: 13515
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 CompletableFuture
s because you can obtain Future
s 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.
Upvotes: 4
Reputation: 844
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
Upvotes: 1