Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ExecutorService任务生成_Java_Coding Style_Refactoring_Executorservice - Fatal编程技术网

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
,用于处理一系列任务。任务由my
DaemonTask
类表示,每个任务都构建一个响应对象,该对象被传递给响应调用(不在本问题的范围内)。我正在使用
switch
语句根据任务id
int
生成相应的任务。它看起来像

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