Посоветуйте лучший способ превратить синхронные методы в асинхронные в Java - PullRequest
3 голосов
/ 11 марта 2010

В классах есть несколько методов, которые выполняются синхронно. Я хотел бы, чтобы они работали асинхронно, первая идея состояла в том, чтобы обернуть это и использовать switch enum, чтобы решить, какая функция должна быть вызвана. Но для каждого вызванного метода мне требовался новый метод в классе-обертке и новый enum. Это выглядит так:

public class QueuedShow implements InterfaceShowAlert, Runnable {
    private Class Action {
       String param1;
       public static enum ActionEnum{
          NEW, CHECK, UPDATE, DELETE, DISPLAY;
       }
       public ActionEnum todo;
       public Action(ActionEnum todo, Object param){
          this.todo=todo;
          this.param1=param;
       }
    }
    private BlockingQueue<Action> actionList;
    public void run(){
       while(true){
           Action action=actionList.take(); //THIS waits until queue isn't empty
           switch(action.todo){
           case NEW: //Call original function
              ....
           }
       }
    }
    public void new(String param){
       actionList.add(new Action(NEW, param));
    }
}

Тогда я узнал об отражении, и у меня появилась новая идея. То есть вызывать методы, используя строки вместо прямых вызовов методов. Класс-оболочка считывает и анализирует строки, а также получает класс и содержащий метод, используя отражение. Он помещает параметры и объект Method в класс, который помещается в очередь. Теперь класс использует Method.invoke (params) вместо использования enum для переключения. Но проблема в том, что проверка типов во время компиляции потеряна.

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

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

Ответы [ 3 ]

5 голосов
/ 11 марта 2010

Это рекомендуемый способ сделать это:

abstract public class Action<T> implements Runnable {
  private final T param;

  public Action(T param) {
    this.param = param;
  }

  @Override
  public final void run() {
    work(param);
  }

  abstract protected void work(T param);
}

с:

ExecutorService exec = Executors.newSingleThreadExecutor();
while (/* more actions need to be done */) {
  exec.submit(action);
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
4 голосов
/ 11 марта 2010

Обычный способ справиться с этим - использовать среду исполнения java 5 , как показано здесь . Это позволит вам использовать один и тот же шаблон для синхронных и асинхронных реализаций, и вы можете просто выбрать, какой ExecutorService использовать.

1 голос
/ 11 марта 2010

Но это то же самое, что krosenvoid, это означает, что обертка класс нужен для каждого метода, реализует метод работы (param) сейчас.

Либо вы идете за чем-то, что является полностью динамичным и отражающим, где вы передаете String для имени метода и Object для параметра. Поскольку Java статически типизирован (в отличие от динамического языка, такого как Groovy), он будет ужасным и, вероятно, полон кастинга, но вы можете это сделать.

Текущее решение перечисляет асинхронный метод с enums. Так что он не полностью динамический и расширяемый, не изменяя код. То есть вам нужно будет добавить новый enum для каждого нового метода.

public static enum ActionEnum{
          NEW, CHECK, UPDATE, DELETE, DISPLAY;
}

Если для вас все в порядке, также следует использовать Action или Callable, как предлагается в других ответах. Для каждого нового метода вам нужно написать новый Action или Callable, чтобы вызов метода определялся статически.

 protected void work(String param)
 {
      myObject.theMethodToDispatch( param );
 }

Я согласен, что это немного более стандартный код, но он все еще довольно мал. Большой выигрыш в том, что ваш код не является отражающим (и не должно быть приведения), и вы получаете преимущество статически типизированных языков: вы можете рефакторировать имена методов, компилятор предупреждает вас, если параметр типа не соответствует и т. д.

...