我需要实现一个使用(双向)请求-响应协议(protocol)同时与多个客户端通信的应用程序。以前我已经为每个客户端使用两个专用线程(一个读取器/ react 器和一个写入器/启动器)实现了这一点。这样做的问题是线程管理变得非常复杂和丑陋。有没有任何标准的方法来处理这个问题,甚至可能只有一个线程,或者至少有一个恒定数量的线程来处理所有客户端?
这是某种通信在具有阻塞实现的线程中的样子:
Command response = request("cmd1", "a", "b");
if(!response.is("OK")) {
return;
}
response = request("cmd2", "c");
if(!response.is("OK")) {
return;
}
response = request("cmd3");
在发送请求和等待相应响应之间,我希望当前线程能够执行其他工作,但是一旦响应实际到达就继续执行。
我知道可以使用异步 IO 并注册 Java Future/Runnable 实例以在收到请求响应后运行,但这很容易变成匿名 Runnable 子类的多层嵌套,我怀疑它会比它值得的更痛苦。这可能会导致类似于下面的示例,它很快就会变得高度嵌套且不可读。一定有更简单的方法吗?
request("cmd1", "a", "b", new ResponseHandler() {
public void response(Command response) {
if(response.is("OK")) {
request("cmd2", "c", new ResponseHandler() {
public void response(Command response) {
if(response.is("OK")) {
request("cmd3", new NullResponseHandler());
}
}});
}
}});
我也考虑过使用专用 Actor framework 的可能性处理请求-响应逻辑。虽然它们看起来可以在这种情况下提供帮助,但我以前从未使用过此类框架,所以我不知道它们是否适合这种情况。
简而言之,我的问题是:如何以非阻塞方式处理任意数量的请求-响应连接,以便恒定数量的线程就足够了? Actor 框架是一种有效的方法吗?
附言。我在这个项目中使用 Java。
最佳答案
我认为使用一些 Java NIO 框架(例如netty .还没有使用过 Actor 框架,所以不知道这是否更合适。
基本上,您创建一个类来处理整个通信并存储必要的信息——框架在后台处理整个线程,您只需提供一个方法,例如messageReceived 并在那里处理。
缺点是,基本上您必须编写自己的状态机,这可能不是那么简单 - 但它肯定是使用 NIO 的最简单方法。
示例:
enum State {
S0, S1
}
private State state = State.S0;
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
switch(state) {
case S0:
// read object from channel and write appropriate response
e.getChannel().write("HELO"); // writes are asynchronous
state = State.S1;
break;
case S1:
// same as S0
e.getChannel().write("DONE");
break;
}
}
请注意,阅读 netty 教程仍然是绝对必要的,因为有些关于 NIO 的东西是无法 self 解释的(至少对我来说不是)。但是有几个易于理解的示例应该可以教给您一些基础知识。
关于java - 如何在等待响应时不阻塞地实现请求-响应协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7859648/