MethodArgumentReader和MethodArgumentWriter也是对于ValueReader和ValueWriter的封装,其实跟ContentHeaderPropertyReader和ContentHeaderPropertyWriter类似的,只是读写内容不同,ContentHeaderProperty是基础属性,而MethArgument读写AMQP的协议指令(Method具体实现),比如说队列声明,发布消息等,我们来具体看一下它与ContentHeaderPropertyWriter/Reader具体有什么异同
1、成员变量
| 变量名 | 默认值 | 描述 |
|---|---|---|
| final ValueWriter out | 构造方法传入对象 | |
| boolean needBitFlush | false | 写入Method布尔属性就true,否则就false |
| byte bitAccumulator | 0 | 存Method的布尔值属性,二进位0或1刚好表示,有点类似flagWord |
| int bitMask | 1 | 辅助bitAccumulator的bit设置 |
2、方法
| 方法名 | 描述 | 图示 |
|---|---|---|
| MethodArgumentWriter(ValueWriter out) | 构造方法,重置成员变量 | |
| final void writeShortstr | 写short字符串 | |
| final void writeLongstr(LongString str) | 写入长的字符串 | |
| final void writeLongstr(String str) | 写入长的字符串 | |
| final void writeShort(int s) | 写入short | |
| final void writeLong(int l) | 写入int值 | |
| final void writeLonglong(long ll) | 写入long值 | |
| final void writeBit(boolean b) | 写入boolean的位 | 1 |
| final void writeTable(Map<String, Object> table) | 写入map值 | |
| final void writeOctet(int octet) | 写入byte值 | |
| final void writeTimestamp(Date timestamp) | 写入时间戳 | |
| final void flush() | 这里就写入bit值(如果未写入的话) |
2.1、图示
- writeBit(boolean b)
- 一个byte位有8位,一个byte可以表示8个boolean值属性的值,如果大于8位之后就写下一个byte值

- 总结
- 判断当然byte的所有8位是否被占有的,如果被占有,当然需要当前bit写到流中,同时需要重置新的byte的需要初始化(从0开始新的byte)
- 如果传入值是true,说明需要将对应byte置为1,也通过进行或运算,同时你也会发现,说明提前把对应位置移动好的
- 向左移动一位bitMask,为下一次异或做准备
- 标记说这个bitAccumulator有意义boolean属性值存着,需要写入流中,同时你会发现,怎么没有写操作呢,如果没有触发1,那么就不会写入到流中吗?其实它的每个方法都有一个bitFlush()调用,同时在重写flush方法中也有bitFlush(),所有个写入值可能是在flush操作写入的, 具体你可以查看Method抽象类的toFrame方法
3、MethodArgumentReader 类
- 与之MethodArgumentWriter的写类, MethodArgumentReader是读取MethodArgumentWriter写的数据,也就逆过程
3.1、成员变量
| 变量名 | 默认值 | 描述 |
|---|---|---|
| final ValueReader in | 构造方法传入对象 | |
| int bits | 0 | 读取存在boolean属性的byte值 |
| int nextBitMask | 0x100 | 辅助确定bits某个位置是1还0,二进制表示 1 0000 0000 [前置零省略了] |
3.2、方法
| 方法名 | 描述 | 图示 |
|---|---|---|
| MethodArgumentReader(ValueReader in) | 构造方法,重置成员变量 | |
| final String readShortstr() | 读short字符串 | |
| final LongString readLongstr() | 读入长的字符串 | |
| final int readShort() | 读入short值 | |
| final long readLonglong() | 读入long值 | |
| final int readLong() | 读入int值 | |
| final boolean readBit() | 读入boolean的位 | 1 |
| final void Map<String, Object> readTable() | 读入map值 | |
| final int readOctet() | 读入byte值 | |
| final Date readTimestamp() | 读入时间戳 |
3.3、图示
- boolean readBit()

- 总结
- 判断是否大于8位了,如果大于的话表示当前byte已经读取完了,需要读取下一个byte值,同时重置,继续从0开始(第一个位置)
- 进行二进制与运算,判断该位置是否为1,为1表示为true,否则为false
- 移动下一个位置(向左移动一位)
3、总结
| 异同点 | MethodArgumentReader(Writer) | ContentHeaderPropertyReader(Writer) |
|---|---|---|
| 1 | 都是使用ValueWriter(Reader) | 都是使用ValueWriter(Reader) |
| 2 | read/writeBit() 为表示boolean值 | flagWord进制位表示某个属性是否存在 |
| 3 | 由于Method实现不同,属性不是固定 | 属性是固定的,14个属性 |
| 4 | 对于boolean特殊处理 | 没有boolean值 |
-
本质上是就是对于ValueWriter具体应用,也就是定义规则,由于ContentHeaderProperty属性是固定的,所有它是利用flagWord表示某个属性是否存在,
-
MethodArgument实现不是固定的,属性类型和数量都不一样呢,这个时候它只是为节省boolean值存在空间,利用byte值来存在,一个byte值最多可以存储8个boolean值属性。
-
其实这个也是可以学习的定义,合理利用二进制的位来保存boolean值,其实应用比较广泛就是redis的布隆过滤器呢。
-
希望能对您有所帮助和启发
本文深入探讨AMQP协议中MethodArgumentReader和MethodArgumentWriter的作用,它们是对ValueReader和ValueWriter的封装,分别用于读写AMQP方法指令。文章详细分析了两者之间的异同,特别是在处理boolean属性时的位操作优化,以及在内存和流中的读写操作。此外,还介绍了如何利用位运算高效存储和读取多个boolean值,这一技巧在数据存储和过滤器如布隆过滤器中有广泛应用。

被折叠的 条评论
为什么被折叠?



