Java ExecutorCompletionService作为API响应程序

时间:2012-11-16 19:53:10

标签: java api executorservice threadpoolexecutor

我有一个服务器应用程序,可以在ServerSocket上侦听传入的查询。提交查询的客户端希望打开服务器的套接字,向上游传递查询,然后(可能在很短的一段时间后)从他们使用的相同的套接字读取对查询的响应提交查询。

为此,我尝试使用ExecutorCompletionService。不同的查询类会传递给不同的Callable,但所有查询类都会返回String作为结果。

所有这些都是可以管理的,直到我到达实际尝试回复客户端的阶段。 Future对象目前都是Future<String>类型,但我无法将结果(String)与相应的Socket结合。

我的解决方案是让我的所有Callable类型为Callable<StringSocketPair>,其中StringSocketPair看起来像;

public class StringSocketPair {
    Socket sock;
    String content;
}

但这一切似乎都有些奇怪,因为现在我必须将Socket传递给Callable构造函数,以便它可以将String结果与call()结果一起返回1}}方法。所有这些都是为了让我可以将String推到另一个轮询Socket的{​​{1}}中。

另一种选择是使用ExecutorCompletionService.take()而不是Runnable s并让每个Callable任务自行回复Runnable,但因为我有十几个左右查询类型,每个都有自己的任务对象,而且我不必为每个任务对象的每个Socket方法的末尾添加某种respondToClient()调用。

对于我认为相当常见的设置,必须有一个更简单的解决方案吗?

1 个答案:

答案 0 :(得分:2)

遵循使用Runnable的想法,您可以使用Template Method Pattern来定义响应功能。这将阻止您为每个任务编写公共代码,因为公共代码将放在实现Runnable的抽象父类中。

模板方法模式:

abstract class TemplateSuperClass implements Runnable {
    public void run() {
        //some setup code here
        String message = taskWork(...);
        socket.write(message);
        //common cleanup code
    }

    abstract String taskWork(...);
}

class HelloWorld extends TemplateSuperClass {
    String taskWork(...) {
        return "Hello World";
    }
}

否则,您可能更改Callable以返回响应消息和套接字的元组。