3

在一个类中有一些同步运行的方法。我希望它们异步运行,第一个想法是包装它,并使用 switch 枚举来决定应该调用哪个函数。但是对于每个调用的方法,我都需要包装类中的一个新方法和一个新的枚举。它看起来像这样:

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) 而不是使用枚举进行切换。但是这个问题是编译器时类型检查丢失了。

当然,所有这些都只适用于无效的方法,但当然我们也可以使用 Future 类来返回值。

现在是否有任何框架已经实现了将同步调用转换为异步调用,或者您知道执行此操作的任何其他方法。

4

3 回答 3

5

这是推荐的方法:

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);
于 2010-03-11T07:29:52.743 回答
4

处理此问题的正常方法是使用 java 5执行器框架,如下所示。这将允许您对同步和异步实现使用相同的模式,并且您可以选择使用哪个 ExecutorService。

于 2010-03-11T07:23:11.337 回答
1

但这和 krosenvoid 是一样的,这意味着每个方法都需要一个包装类,现在实现一个 work(param) 方法。

要么你选择完全动态和反射的东西,你传递String方法名称和Object参数。因为 Java 是静态类型的(不像 Groovy 之类的动态语言),这将是可怕的并且可能充满了强制转换,但你可以做到。

您当前的解决方案列出了带有enums. 因此,如果不更改代码,它也不是完全动态和可扩展的。也就是说,您需要enum为每个新方法添加一个新方法。

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

如果对您没问题,也应该可以使用Actionor Callable,如其他答案中所建议的那样。对于每个新方法,您都需要编写一个新的ActionorCallable以便静态定义方法调用。

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

我同意这是一个更多样板代码,但这仍然相当小。最大的好处是,您的代码不是反射式的(并且不应该进行强制转换),并且您可以从静态类型语言中受益:您可以重构方法名称,编译器会在类型参数不匹配时向您发出警告等。

于 2010-03-11T09:30:37.100 回答