Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callable with different return types

I would like to execute different methods in a separate thread depending on the parameters that are given to the constructor. However, the Callable interface only allows one kind of return parameter.

It should work like this:

Future<String> result =
       executor.submit(ClassThatImplementsCallable(RETURN_STRING));
Future<Integer> result =
       executor.submit(ClassThatImplementsCallable(RETURN_INT));

ClassThatImplementsCallable(RETURN_NOTHING);

To return either null (respectively the reference to Void) or any other type like String or Integer I have to use T without any bounds like this:

public static class CallableTest<T> implements Callable<T>{
    T value;
    CallableTest(T value) {
       this.value = value;
    }
    public T call(){    
       return value;   
    }    
}

However, this is not what I want to achieve, but it also doesn't make sense to extend Void and implement some other interface.

like image 964
user1812379 Avatar asked Jun 03 '13 20:06

user1812379


2 Answers

I would like to execute different methods in a separate thread depending on the parameters that are given to the constructor.

So when you submit a Callable to an ExecutorService, you get a future with the same type:

Future<String> stringResult = executor.submit(new MyCallable<String>());
Future<Integer> stringResult = executor.submit(new MyCallable<Integer>());

What you can't do is have a single Future result that returns one of two different types, either String or Integer, based on arguments when the ExecutorService was constructed. I think that is what you are asking.

One alternative would be for you to create a little wrapper class:

public class StringOrInteger {
    final String s;
    final Integer i;
    public StringOrInteger(String s) {
        this.s = s;
        this.i = null;
    }
    public StringOrInteger(Integer i) {
        this.s = null;
        this.i = i;
    }
    public boolean isString() {
        return this.s != null;
    }
}

Then your executor will submit Callable<StringOrInteger> and the instances of StringOrInteger returned by the Future<StringOrInteger> will either the s or i field will be set.

An extremely ugly alternative would be to return Object and use instanceof to figure out what type it is. But I won't even show the code for that implementation because it would give me hives.

like image 72
Gray Avatar answered Oct 04 '22 23:10

Gray


you could use the Command pattern together with Visitor pattern.

Define a command class and wrap your processing logic together with parameters and return types in it. then pass this command object as parameter and also use it as result type.

Later in your code you can use visitor pattern in order to deal with the two concrete commands.

like image 41
Steve Oh Avatar answered Oct 04 '22 23:10

Steve Oh