Java ExecutorService任务生成
我有一个Java ExecutorService任务生成,java,coding-style,refactoring,executorservice,Java,Coding Style,Refactoring,Executorservice,我有一个ExecutorService,用于处理一系列任务。任务由myDaemonTask类表示,每个任务都构建一个响应对象,该对象被传递给响应调用(不在本问题的范围内)。我正在使用switch语句根据任务idint生成相应的任务。它看起来像 //in my api listening thread executorService.submit(DaemonTask.buildTask(int taskID)); 我的所有任务类(例如WiggleTask())扩展DaemonTask,并为
ExecutorService
,用于处理一系列任务。任务由myDaemonTask
类表示,每个任务都构建一个响应对象,该对象被传递给响应调用(不在本问题的范围内)。我正在使用switch
语句根据任务idint
生成相应的任务。它看起来像
//in my api listening thread
executorService.submit(DaemonTask.buildTask(int taskID));
我的所有任务类(例如
WiggleTask()
)扩展DaemonTask
,并为execute()
方法提供实现
我的问题很简单;这种模式合理吗?当我看到巨大的开关盒及其所有返回语句时,感觉有些不对劲。我曾试图以某种方式提出一种更优雅的使用反射的查找表解决方案,但似乎无法找到一种可行的方法。您可以使用
enum
:
public enum TaskBuilder
{
// Task definitions
TASK_A_ID(1){
@Override
public DaemonTask newTask()
{
return new WiggleTask();
}
},
// etc
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int taskID;
public abstract DaemonTask newTask();
TaskBuilder(final int taskID)
{
this.taskID = taskID;
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
另一种可能是使用构造函数字段而不是方法,即使用反射。编写起来容易得多,而且工作正常,但是异常处理会变成一场噩梦:
private enum TaskBuilder
{
TASK_ID_A(1, WiggleTask.class),
// others
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int index;
private final Constructor<? extends DaemonTask> constructor;
TaskBuilder(final int index, final Class<? extends DaemonTask> c)
{
this.index = index;
// This can fail...
try {
constructor = c.getConstructor();
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
// Ewww, three exceptions :(
public DaemonTask newTask()
throws IllegalAccessException, InvocationTargetException,
InstantiationException
{
return constructor.newInstance();
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
私有枚举任务生成器
{
TASK_ID_A(1,WiggleTask.class),
//其他
//构建查找映射
私有静态最终映射查找\u映射
=新HashMap();
静止的{
对于(最终TaskBuilder:values())
查找映射放置(builder.taskID,builder);
}
私有最终整数指数;
私有最终构造函数您真的需要这么多类吗?每个taskId可以有一个方法
final ResponseHandler handler = ... // has many methods.
// use a map or array or enum to translate transIds into method names.
final Method method = handler.getClass().getMethod(taskArray[taskID]);
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
method.invoke(handler);
}
});
final ResponseHandler=…//有许多方法。
//使用映射、数组或枚举将transid转换为方法名。
final-Method=handler.getClass().getMethod(taskArray[taskID]);
executorService.submit(新的可调用(){
public Void call()引发异常{
调用(处理程序);
}
});
如果你必须有很多课程,你可以这样做
// use a map or array or enum to translate transIds into methods.
final Runnable runs = Class.forName(taskClassArray[taskID]).newInstance();
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
runs.run();
}
});
//使用映射、数组或枚举将transid转换为方法。
final Runnable runs=Class.forName(taskClassArray[taskID]).newInstance();
executorService.submit(新的可调用(){
public Void call()引发异常{
runs.run();
}
});
重载使用得很好,我会记住这个模式的,谢谢!不过更简单的是:您可以添加一个类作为枚举的实例变量,然后.newTask()
将只是一个类。newInstance()
.Your choice;)使用抽象方法的优点是,您可以在初始化时做更多的工作。我可能最终会使用此方法,如果我这样做,我会将accept移到另一个位置。再次感谢您的想法。这是我试图掌握的基于反射的方法。感谢您用两个示例对其进行说明。我解释了使用单独类的原因简单地说,execute()
方法在很多情况下都是巨大的,有些方法需要库,而另一些方法则不需要库等等。每个方法都有一个类,这意味着源文件大小合理,避免了数百万次导入。
final ResponseHandler handler = ... // has many methods.
// use a map or array or enum to translate transIds into method names.
final Method method = handler.getClass().getMethod(taskArray[taskID]);
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
method.invoke(handler);
}
});
// use a map or array or enum to translate transIds into methods.
final Runnable runs = Class.forName(taskClassArray[taskID]).newInstance();
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
runs.run();
}
});