2013-06-03 4 views
4

Я хотел бы выполнять разные методы в отдельном потоке в зависимости от параметров, предоставляемых конструктору. Однако интерфейс Callable позволяет только один из параметров возврата.Вызываем с разными типами возвращаемых данных

Он должен работать так:

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

ClassThatImplementsCallable(RETURN_NOTHING); 

Для возврата либо нулевой (соответственно ссылку на VOID) или любого другого типа, как строка или целое число, я должен использовать T без каких-либо границ, как это:

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

Однако это не то, чего я хочу достичь, но также не имеет смысла расширять Void и реализовывать какой-либо другой интерфейс.

+1

Если они не возвращают то же самое, они, вероятно, должны быть разными способами. Вы всегда можете вернуть значения игнорирования метода, чтобы вы знали. – thatidiotguy

ответ

7

Я хотел бы выполнить различные методы в отдельном потоке в зависимости от параметров, которые присваиваются конструктору.

Итак, когда вы подать Callable к ExecutorService, вы получите будущее с тем же типом:

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

Что вы не может сделать, это есть один Future result, который возвращает один из двух различные типы, либо String, либо Integer, на основе аргументов при построении ExecutorService. Я думаю, это то, о чем вы просите.

Одна альтернатива была бы для вас, чтобы создать маленький класс обертку:

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; 
    } 
} 

Тогда ваш исполнитель будет представлять Callable<StringOrInteger> и либо будут установлены случаи StringOrInteger возвращаемые Future<StringOrInteger> поле s или i.

Крайне уродливой альтернативой было бы вернуть Object и использовать instanceof, чтобы выяснить, какой тип. Но я даже не покажу код для этой реализации, потому что это даст мне ульи.

+0

Спасибо. Надеюсь, я правильно понял: Generics с параметрами ограниченного типа не может быть решением в этом контексте, потому что разрешены только такие вещи, как ClassThatImplementsCallable реализует Callable ? Как я могу сделать метод вызова Callable return void или какой-либо другой тип? – user1812379

+0

Что? Данный «Исполнитель» может обрабатывать «Callable's» с любым возвращаемым типом. Вам просто нужно передать ему 'Callable ' соответствующего 'T'. Было бы неплохо иметь 'executor.submit (новый ClassThatImplementsCallable (RETURN_STRING)); исполнитель.submit (новый ClassThatImplementsCallable (RETURN_INT)); ' –

+0

Да, мне нужно исправить часть моего ответа @LouisWasserman. Благодарю. Я даже не думал о передаче 'Callable', которые возвращают разные типы в« ExecutorService », но это можно сделать. – Gray

1

вы можете использовать шаблон команды вместе с шаблоном посетителя.

Определите класс команд и заверните свою логику обработки вместе с параметрами и типами возврата. затем передать этот объект команды в качестве параметра, а также использовать его как тип результата.

Позже в вашем коде вы можете использовать шаблон посетителя, чтобы иметь дело с двумя конкретными командами.

Смежные вопросы