在类中有一些同步运行的方法。我希望它们以异步方式运行,第一个想法是包装它,并使用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类来返回值。
现在是否已经实现了将同步调用转换为异步调用的框架,或者您知道其他任何方法都可以执行此操作。
答案 0 :(得分: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);
答案 1 :(得分:4)
处理此问题的常用方法是使用java 5 executors framework,如图所示here。这将允许您对同步和异步实现使用相同的模式,您只需选择要使用的ExecutorService。
答案 2 :(得分:1)
但这与此相同 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 );
}
我同意这是一个样板代码,但仍然相当小。最大的胜利是那时你的代码没有反思(并且应该没有强制转换)并且你有静态类型语言的好处:你可以重构方法名称,如果类型参数不匹配,编译器会发出警告等等。