推荐一种在Java中将同步方法转为异步的更好方法

发布于 2024-08-24 21:39:50 字数 1155 浏览 4 评论 0原文

类中有一些同步运行的方法。我希望它们异步运行,第一个想法是包装它,并使用 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.invoke(params) 而不是使用枚举进行切换。但这样做的问题是编译时类型检查丢失了。

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

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

In a classes are some methods that are run synchronously. I would like them to run asynchronously, the first idea was to wrap it, and use switch enum to decide which function should be called. But for every method called, I needed a new method in the wrapper class and a new enum. It looks like this:

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

Then I learned about reflection and I got a new idea. That is to invoke methods using strings instead of direct method calls.
The wrapper class reads and parses the strings, and gets the class and containing method using reflection. It puts the parameters and Method object into a class, which is put into a queue. Now the class uses Method.invoke(params) instead of using a enum to switch. But the problem of this is that compiler time type checking is lost.

Of course, all this works for only methods that are void, but of course we could use the Future class to return values too.

Now is there any framework that already has implemented turning synchronous calls to asynchronous ones, or do you know of any other method that does this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自由如风 2024-08-31 21:39:50

这是推荐的方法:使用

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

This is the recommended way of doing it:

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

with:

ExecutorService exec = Executors.newSingleThreadExecutor();
while (/* more actions need to be done */) {
  exec.submit(action);
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
时光与爱终年不遇 2024-08-31 21:39:50

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

The normal way to handle this is to use the java 5 executors framework, like shown here. This'll allow you to use the same pattern for both synchronous and asynchronous implementations, and you can just choose which ExecutorService to use.

与风相奔跑 2024-08-31 21:39:50

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

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

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

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

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

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

我同意这是更多的样板代码,但仍然相当小。最大的胜利是,你的代码不是反射(并且不应该进行强制转换),并且你可以享受静态类型语言的好处:你可以重构方法名称,如果类型参数不匹配,编译器会警告你, ETC。

But that is the same thing as
krosenvoid, it means that a wrapper
class is needed for every method,
implementing a work(param) method now.

Either you go for something that is fully dynamic and reflective, where you pass String for method name and Object for parameter. Because Java is statically typed (unlike dynamic language like Groovy) that will be horrible and probably full of casting, but you can do it.

You current solution lists the asynchronous method with enums. So it's not fully dynamic and extensible neither without changing the code. That is, you will need to add a new enum for each new method.

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

If it's ok for you, it should also be ok to use Action or Callable, as suggested in the other answers. For each new method you will need to write a new Action or Callable so that the method invocation is statically defined.

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

I agree that it's a bit more boilerplate code, but that's still fairly small. The big win is that then your code is not reflective (and there should be no casting) and you have the benefit of statically typed languages: you can refactor method names, the compiler warns you if type parameter mismatch, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文