Java 如何使用netty在单独的线程池中执行业务逻辑处理程序
我有一个需要执行一些业务逻辑的处理程序,我希望它在单独的线程池中执行,以避免阻塞io事件循环。我已将DefaultEventExecutorGroup添加到javadoc和wiki中指定的管道中: 出于测试目的,我的ServerHandler将当前线程休眠5秒钟:Java 如何使用netty在单独的线程池中执行业务逻辑处理程序,java,multithreading,netty,handler,Java,Multithreading,Netty,Handler,我有一个需要执行一些业务逻辑的处理程序,我希望它在单独的线程池中执行,以避免阻塞io事件循环。我已将DefaultEventExecutorGroup添加到javadoc和wiki中指定的管道中: 出于测试目的,我的ServerHandler将当前线程休眠5秒钟: protected void channelRead0(ChannelHandlerContext ctx, Command cmd) throws Exception { System.out.println("Starti
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.
我遗漏了什么?因为
Netty
处理同一个EventExecutor
从同一个套接字发送的请求,所以您可以启动多个客户端,并查看结果。如果您的目标不是阻止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,以便在处理完成时返回响应。是否可以将每个新请求作为提交到线程池的单独任务处理,而不为每个套接字分配线程?我希望来自同一个客户端的请求也能并行运行。@TTT您可以将
命令
实例放入方法channelRead
上的BlockingQueue
容器中,然后在其他线程上的您自己的executor服务中处理它。嗯,当然,我总是可以手动完成这项工作,但有没有什么烦人的方法来完成这项工作呢?既然我可以将EventExecutorGroup传递给我的管道处理程序,那么我是否可以告诉它不要使用每套接字一个线程的方法?@TTT netty方法就是您在自己的代码中所采用的方法。如果您的目标不是阻止IO线程,那么您做得对。如果您希望在阻塞任务到达后立即并行执行,则需要创建单独的线程池。他是否应该重用EventExecutorGroup,并且不要在每次将处理程序添加到管道时都创建一个新的线程池?@Eric这取决于业务逻辑。一般来说,是的,他不应该。
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.");
}
});
}