Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute methods which returns different objects using Executors in Java

I have 4 methods which return List of Different classes. Lets Say

public List<A> getA(String param1, String param2){
 //some code here
}
public List<B> getB(String param1, String param2){
 //some code here
}

public List<C> getC(String param1, String param2){
 //some code here
}
public List<D> getD(String param1, String param2){
 //some code here
}

I want to execute these 4 methods simultaneously, I am using Callable and Executor as bellow

Callable<List<A>> collableA = new Callable<List<A>>() {
        @Override
        public List<A> call() throws Exception {
            return getA();
        }
    };
Callable<List<B>> collableB = new Callable<List<B>>() {
        @Override
        public List<B> call() throws Exception {
            return getB();
        }
    };
Callable<List<D>> collableD = new Callable<List<D>>() {
        @Override
        public List<D> call() throws Exception {
            return getD();
        }
    };
Callable<List<C>> collableC = new Callable<List<C>>() {
        @Override
        public List<C> call() throws Exception {
            return getC();
        }
    };

// add to a list
List<Callable> taskList = new ArrayList<Callable>();
taskList.add(collableA );
taskList.add(collableB);
taskList.add(collableC);
taskList.add(collableD);
//create a pool executor with 4 threads
ExecutorService executor = Executors.newFixedThreadPool(4);

Future<List<FrozenFrameAlert>>  futureFrozen = executor.submit(taskList); 
// getting error here submit() not accepting taskList

I tried with InvokeAll() and invokeAny() methods but no method is accepting this taskList

like image 798
Sat Avatar asked Jul 17 '26 12:07

Sat


2 Answers

Just use submit() for each callable; that will give you four futures, each with the right type:

Future<List<A>> futureA = executor.submit(callableA);
Future<List<B>> futureB = executor.submit(callableB);
etc.

If you need the results of all four futures before you continue, you can just block on each one in turn:

List<A> resultA = futureA.get();
List<B> resultB = futureB.get();
etc.

To do something more generalized, you'd need to figure out a way in which all these lists are "the same". If you don't use them the same way, though, it doesn't matter that they're different types.

like image 190
Daniel Pryden Avatar answered Jul 20 '26 02:07

Daniel Pryden


I found the solution, you simply need to use the generic interface Callable<T> instead of Callable for the ExecutorService#invokeAll(Collection<? extends Callable<T>> tasks) method to accept the List<Callable<T>>.

Example:

List<Callable<List<?>>> taskList = new ArrayList<>();
taskList.add(() -> new ArrayList<>(Arrays.asList(1,2,3)));
taskList.add(() -> new ArrayList<>(Arrays.asList("a","b","c")));
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<List<?>>> futureList = executor.invokeAll(taskList);

for (Future<List<?>> future : futureList) {
    System.out.println(future.get());
}

If you really have different return types you still need to use Callable<T> with some appropriate type, like a super interface or Object at least.

like image 32
xander Avatar answered Jul 20 '26 01:07

xander