Netty 中队列的使用
任务队列中的Task有3种典型使用场景
用户程序自定义的普通任务
NettyServerHandler代码有改动:
package com.ronnie.netty.sample; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil; /**
* 1. 自定义一个Handler需要继承 netty 规定好的某个 HandlerAdapter(适配器模式)
* 2. 这时我们自定义一个Handler, 才能称为一个handler
*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter { /**
* 读取数据事件(这里我们可以读取客户端发送的消息)
* ChannelHandlerContext ctx: 上下文对象, 含有管道 pipeline, 通道 channel, 地址 address
* Object msg: 就是客户端发送的数据 默认Object
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { /* 比如这里我们有一个非常耗时的业务 -> 异步执行 -> 提交该channel对应的
NioEventLoop 的 taskQueue中
*/ // 解决方案1: 用户程序自定义的普通任务
ctx.channel().eventLoop().execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10 * 1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, client, atme ", CharsetUtil.UTF_8));
} catch (InterruptedException e) {
System.out.println("Exception occurs: " + e.getMessage());
}
}
});
ctx.channel().eventLoop().execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(20 * 1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, client, yang ", CharsetUtil.UTF_8));
} catch (InterruptedException e) {
System.out.println("Exception occurs: " + e.getMessage());
}
}
}); // Thread.sleep(10 * 1000);
// ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, client, atme ", CharsetUtil.UTF_8)); System.out.println("go on ...");
// System.out.println("The server is reading thread: " + Thread.currentThread().getName());
// System.out.println("server ctx = " + ctx);
// System.out.println("Check the relationship between channel and pipeline");
// Channel channel = ctx.channel();
// ChannelPipeline pipeline = ctx.pipeline(); // 本质是一个双向链表, 涉及到出栈入栈问题
// // 将 msg转成一个 ByteBuf(是netty提供的, 不是NIO的 ByteBuffer, 性能更高)
// ByteBuf buf = (ByteBuf) msg;
// System.out.println("The message that client send: " + buf.toString(CharsetUtil.UTF_8));
// System.out.println("The address of client: " + ctx.channel().remoteAddress());
} /**
* 数据读取完毕
* @param ctx
* @throws Exception
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { // write + flush, 将数据写入到缓冲并刷新
// 一般来说, 我们对发送的数据进行编码
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, dear client, Kappa", CharsetUtil.UTF_8)); } /**
* 处理异常, 一般需要关闭通道
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}打上断点,debug启动
左键点击ctx
pipeline -> channel -> eventLoop -> taskQueue
可以看到两个线程任务存入了任务队列中
用户自定义定时任务
在NettyServerHandler中之前添加的任务线程代码之下, 打印go on之前添加以下代码:
// 用户自定义定时任务 -> 该任务是提交到 scheduleTaskQueue中的
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(20 * 1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, client, yyf ", CharsetUtil.UTF_8));
} catch (InterruptedException e) {
System.out.println("Exception occurs: " + e.getMessage());
}
}
}, 5, TimeUnit.SECONDS);
打上断点, debug启动
左键点击ctx
pipeline -> channel -> eventLoop -> taskQueue
你会发现taskQueue中只有2个线程任务
我们刚刚写的那个任务在scheduledTaskQueue中(pipeline -> channel -> eventLoop -> scheduledTaskQueue)
非当前Reactor 线程调用Channel的各种方法
- 例如在推送系统的业务线程中, 根据用户的标识, 找到对应的Channel引用, 然后调用 Write 类方法向该用户推送消息, 就会进入到这种场景。最终的Write会提交到任务队列中后被异步消费。
Netty 方案再说明
- Netty 抽象出两组线程池, BossGroup 专门负责接收客户端连接, WorkerGroup 专门负责网络读写操作。
- NioEventLoop表示一个不断循环执行处理任务的线程, 每个 NioEventLoop都有一个selector, 用于监听绑定在其上的socket网络通道。
- NioEventLoop内部采用串行化设计, 从消息的读取 -> 解码 -> 处理 -> 编码 -> 发送, 始终由 IO 线程 NioEventLoop 负责
- NioEventLoopGroup下包含多个NioEventLoop
- 每个NioEventLoop 中包含有一个Selector, 一个 taskQueue
- 每个NioEventLoop 中的 Selector 上可以注册监听多个 NioChannel
- 每个NioChannel 只会绑定在唯一的NioEventLoop上
- 每个NioChannel 都绑定有一个自己的 ChannelPipline
Netty 中队列的使用的更多相关文章
- Netty中的基本组件及关系
原文:https://blog.csdn.net/summerZBH123/article/details/79344226--------------------- 概述 这篇文章主要是用来 ...
- Netty 中ChannelOption的含义以及使用的场景
Netty 中ChannelOption的含义以及使用的场景 转自:http://www.cnblogs.com/googlemeoften/p/6082785.html 1.ChannelOptio ...
- Netty中的那些坑
Netty中的那些坑(上篇) 最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty.在使用过程中一边优化,一边解决各种坑.儿这些坑大部分基本上是Netty4对Netty3的改进部 ...
- netty中的EventLoop和EventLoopGroup
Netty框架的主要线程就是I/O线程,线程模型设计的好坏,决定了系统的吞吐量.并发性和安全性等架构质量属性. 一.Netty的线程模型 在讨论Netty线程模型时候,一般首先会想到的是经典的Reac ...
- Netty中NioEventLoopGroup的创建源码分析
NioEventLoopGroup的无参构造: public NioEventLoopGroup() { this(0); } 调用了单参的构造: public NioEventLoopGroup(i ...
- netty中的发动机--EventLoop及其实现类NioEventLoop的源码分析
EventLoop 在之前介绍Bootstrap的初始化以及启动过程时,我们多次接触了NioEventLoopGroup这个类,关于这个类的理解,还需要了解netty的线程模型.NioEventLoo ...
- Java网络编程 -- Netty中的ByteBuf
由于JDK中提供的ByteBuffer无法动态扩容,并且API使用复杂等原因,Netty中提供了ByteBuf.Bytebuf的API操作更加便捷,可以动态扩容,提供了多种ByteBuf的实现,以及高 ...
- Netty 中的心跳检测机制
心跳检测一般存在于建立长连接 或者 需要保活的场景. 心跳的使用场景 长连接的应用场景非常的广泛,比如监控系统,IM系统,即时报价系统,推送服务等等.像这些场景都是比较注重实时性,如果每次发送数据都要 ...
- Netty中的一些注意事项--底层基础
转载自http://www.mamicode.com/info-detail-1215305.html 最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty.在使用过程中一边优化 ...
随机推荐
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定单词首字母大写
<!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...
- 利用正则表达式判断Java中的秒钟、分钟、小时、日、月是否符合规则
// 定义校验规则 Pattern patRule = Pattern.compile("判断规则"); // 校验结果 patRule.matcher("判断的对象&q ...
- 使用 TestFight 构建 Beta 测试版本
---恢复内容开始--- Beta测试属于软件开发周期中的一环,测试的重点就是让一些活生生的人去使用你的App,不断测试然后反馈.你需要让你的测试成员发现尽可能多的bug,以便你在公开发布之前将其修复 ...
- Linux centosVMware 集群介绍、keepalived介绍、用keepalived配置高可用集群
一.集群介绍 根据功能划分为两大类:高可用和负载均衡 高可用集群通常为两台服务器,一台工作,另外一台作为冗余,当提供服务的机器宕机,冗余将接替继续提供服务 实现高可用的开源软件有:heartbeat. ...
- Python 基础之生成器
一.生成器表达式 生成器本质是迭代器,允许自定义逻辑的迭代器迭代器和生成器区别:迭代器本身是系统内置的,重写不了.而生成器是用户自定义的,可以重写迭代逻辑生成器可以用来钟方式创建: (1)生成器 ...
- 设计模式课程 设计模式精讲 7-2 建造者模式Coding
1 代码演练 1.1 建造者模式演练 1.2 静态内部类演练建造者模式(链式调用) 1 代码演练 1.1 建造者模式演练 需求: 根据讲师提供的课程名称,课程ppt,课程视频,课程手记,课程问答 制作 ...
- Redis调用
Redis帮助类 using StackExchange.Redis; using System; using System.Collections.Generic; using System.Lin ...
- 【转】iPhone/IOS使用Fiddler抓包配置
原文链接:https://blog.csdn.net/weixin_39198406/article/details/81123716 1. 安装 安装Fiddler软件2. 配置2.1 端口 点击 ...
- js 用于运行string中的<script>和</script>之间的函数
/** * Created by 炜文 on 2017/2/15. */ var intext = '485222<script> var i=2;var j=2;console.log( ...
- Metasploit学习笔记——社会工程学
1.社会工程学攻击案例——伪装木马 Linux命令终端输入命令msfvenom -l payloads用来列出攻击载荷,grep命令用来查询所需要的攻击载荷,条件是windows系统.要有回连至监听主 ...