Sat
Sat

Reputation: 4178

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

Upvotes: 3

Views: 1958

Answers (3)

Daniel Pryden
Daniel Pryden

Reputation: 60997

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.

Upvotes: 2

xander
xander

Reputation: 1765

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.

Upvotes: 1

janith1024
janith1024

Reputation: 1042

The error is saying that your

List<Callable> taskList = new ArrayList<Callable>();

is not generic it should be some thing like .

List<Callable<List>> taskList = new ArrayList<>();

Upvotes: 0

Related Questions