推荐一种在Java中将同步方法转为异步的更好方法
类中有一些同步运行的方法。我希望它们异步运行,第一个想法是包装它,并使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是推荐的方法:使用
:
This is the recommended way of doing it:
with:
处理此问题的正常方法是使用 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.
要么选择完全动态和反射的东西,在其中传递
String
作为方法名称,并传递Object
作为参数。因为 Java 是静态类型的(与 Groovy 这样的动态语言不同),这将是可怕的并且可能充满强制转换,但您可以做到。您当前的解决方案列出了带有
枚举
的异步方法。因此,如果不更改代码,它就不是完全动态的和可扩展的。也就是说,您需要为每个新方法添加一个新的enum
。如果对您来说没问题,那么使用
Action
或Callable
也应该可以,如其他答案中的建议。对于每个新方法,您需要编写一个新的Action
或Callable
以便静态定义方法调用。我同意这是更多的样板代码,但仍然相当小。最大的胜利是,你的代码不是反射(并且不应该进行强制转换),并且你可以享受静态类型语言的好处:你可以重构方法名称,如果类型参数不匹配,编译器会警告你, ETC。
Either you go for something that is fully dynamic and reflective, where you pass
String
for method name andObject
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 newenum
for each new method.If it's ok for you, it should also be ok to use
Action
orCallable
, as suggested in the other answers. For each new method you will need to write a newAction
orCallable
so that the method invocation is statically defined.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.