1.本文总结自 B站 《尚硅谷-netty》;
2.NioEventLoop实际上是一个提交到线程池的Runnable任务,在while无限循环中运行 taskQueue中的任务(串行);
1)NioEventLoop:
2)NioEventLoop 内部采用串行化设计:
3)NioEventLoopGroup 下包含多个 NioEventLoop ;
4)任务提交到 NioEventLoop 后,实际会添加到 taskQueue ;
- /**
- * @Description netty服务器处理器
- * @author xiao tang
- * @version 1.0.0
- * @createTime 2022年08月27日
- */
- public class SimpleNettyServerHandler45 extends ChannelInboundHandlerAdapter {
-
- // 读写数据事件(读取客户端发送的消息)
- // 1. ChannelHandlerContext ctx: 上下文信息,包括管道pipeline,通道channel,地址
- // 2. Object msg: 客户端发送的数据,默认是 Object
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("server ctx = " + ctx);
-
- System.out.println("查看 channel 和 pipeline的关系 ");
- Channel channel = ctx.channel();
- ChannelPipeline channelPipeline = ctx.pipeline(); // 管道是双向链表,出栈入栈
-
-
- // 将 msg 转为 ByteBuf 字节缓冲
- // 这个 ByteBuf 是 netty提供的, 不是 nio的ByteBuffer
- ByteBuf buf = (ByteBuf) msg;
- System.out.println("客户端发送消息:" + buf.toString(StandardCharsets.UTF_8));
- System.out.println("客户端地址:" + ctx.channel().remoteAddress());
-
- // 同步任务1
- // 业务场景: 有一个耗时长的业务 -> 异步执行 -> 提交该 channel对应的 NIOEventLoop 的 taskQueue 中;
- // Thread.sleep(10 * 1000);
- // ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端,我是同步任务1", StandardCharsets.UTF_8));
- // System.out.println("go on.....");
-
- // 以上耗时操作的解决方案1:用户程序自定义的普通任务
- // 异步任务2
- ctx.channel().eventLoop().execute(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(10 * 1000);
- ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端,我是异步任务2-休眠10s", StandardCharsets.UTF_8));
- } catch (Exception e) {
- System.out.println("发生异常, " + e.getMessage());
- }
- }
- });
-
- // 异步任务3
- ctx.channel().eventLoop().execute(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(20 * 1000);
- ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端,我是异步任务3-休眠20s", StandardCharsets.UTF_8));
- } catch (Exception e) {
- System.out.println("发生异常, " + e.getMessage());
- }
- }
- });
- // 异步任务2和异步任务3添加到同一个任务队列,由同一个线程来运行,所以异步任务2阻塞10s,而异步任务3会阻塞30s(10+20)
- System.out.println("异步任务 go on.....");
-
- // 用户自定义定时任务 -》 定时任务提交到 scheduledTaskQueue 中
- ctx.channel().eventLoop().schedule(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(20 * 1000);
- ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端,我是定时任务1-休眠5s", StandardCharsets.UTF_8));
- } catch (Exception e) {
- System.out.println("发生异常, " + e.getMessage());
- }
- }
- }, 5, TimeUnit.SECONDS);
- System.out.println("定时任务 go on.....");
【代码解说】
【补充】taskQueue目录树:
