繁体   English   中英

建议在Java中将同步方法转换为异步的更好方法

[英]Recommend a better way to turn synchronous methods to asynchronous in Java

在类中有一些同步运行的方法。 我希望它们以异步方式运行,第一个想法是包装它,并使用switch 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)而不是使用枚举来切换。 但问题是编译器时间类型检查丢失了。

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

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

这是推荐的方法:

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

处理这种情况正常的方法是使用了Java 5个执行人框架 ,像显示在这里 这将允许您对同步和异步实现使用相同的模式,您只需选择要使用的ExecutorService。

但这与krosenvoid相同,它意味着每个方法都需要一个包装类,现在实现一个work(param)方法。

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

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

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

如果它对你没问题,那么也可以使用ActionCallable ,如其他答案所示。 对于每个新方法,您需要编写一个新的ActionCallable以便静态定义方法调用。

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

我同意这是一个样板代码,但它仍然相当小。 最大的胜利是你的代码不是反射性的 (并且应该没有转换)并且你有静态类型语言的好处:你可以重构方法名称,如果类型参数不匹配,编译器会发出警告等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM