我有一个需要执行某些业务逻辑的处理程序,我希望它在一个单独的线程池中执行,以便不阻塞io事件循环。我已按照http://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html javadoc和http://netty.io/wiki/new-and-noteworthy-in-4.0.html#no-more-executionhandler---its-in-the-core wiki:
中的指定将DefaultEventExecutorGroup添加到管道中ch.pipeline().addLast(new DefaultEventExecutorGroup(10), new ServerHandler());
仅出于测试目的,我的ServerHandler只是让当前线程休眠5秒钟:
protected void channelRead0(ChannelHandlerContext ctx, Command cmd) throws Exception {
System.out.println("Starting.");
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Finished.");
}
但显然业务逻辑仍然是同步执行的:
Starting.
Finished.
Starting.
Finished.
Starting.
Finished.
我错过了什么?
答案 0 :(得分:2)
如果您的目标不是阻止IO事件循环 - 您做得对。但由于特定于netty,您的处理程序将始终附加到EventExecutorGroup的同一个线程,因此您需要执行上述行为。
如果您希望在到达时并行执行阻止操作,则需要使用另一种方式 - 单独ThreadPoolExecutor
。像这样:
ch.pipeline().addLast(new ServerHandler(blockingThreadPool));
其中blockingThreadPool
是常规ThreadPoolExecutor
。
例如:
ExecutorService blockingThreadPool = Executors.newFixedThreadPool(10);
现在,在您的逻辑处理程序中,您可以向此执行程序提交阻塞任务,如下所示:
protected void channelRead0(ChannelHandlerContext ctx, Command cmd) throws Exception {
blockingIOProcessor.execute(new Runnable() {
@Override
public void run() {
System.out.println("Starting.");
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Finished.");
}
});
}
您还可以将上下文传递给此runnable,以便在需要时完成处理后返回响应。
答案 1 :(得分:-1)
因为Netty
处理由同一个套接字通过相同EventExecutor
发出的请求,所以您可以启动多个客户端,并查看结果。