在ZeroMQ(java)中,整个IO的处理流程都是分层来进行的,当然处于最下端的肯定是前面介绍过的poller以及StreamEngin了。。。。涉及到上层的话就还有session,以及socket,先用一张图来大概的描述一下整个层次关系吧。。

整个分层的结构大概就是这样吧,其中poller与StreamEngin是怎么交互的,这个就不说饿了吧,然后Session这个怎么与session之间交互呢,这个以后再说吧,其实在streamEngin里面有自己的session引用。。反正这里没啥意思。。主要就在与Session怎么与自己所属的Socket进行交互,当从最底层接收到数据之后,session如何交给上层的socket,让其来处理。。。这里就涉及到了Pipe,也就是session与自己所属的socket之间是通过pipe来进行数据传递的。。。

那么在具体的分析session与socket之前就来看看这个Pipe是怎么工作的吧,先来大概的看看它的类图:

这里可以看到Pipe继承自ZObject类型,那么可以知道Pipe可以发送,接受以及执行命令,同时也就意味着Pipe也需要由自己关联的IO线程才行,或者说有关联的mailbox。。。不过这个也不是强制的,以后再分析Socket的pipe的时候,就会发现它的pipe关联到socket自己的mailbox,但是socket的mailbox没有注册到任何的poller上面去,也就是它并没有在任何IO线程里执行,最后其实是在用户代码的线程中运行的。。。。好了。好像闲话说的比较多了。。用一张图来刻画一下Pipe是怎么运行的吧:

其实通过这张图形就已经将Pipe的运行原理基本描述出来了,pipe的两端都分别关联了两个YPipe(可以将其理解为队列)对象,例如左边将其中一个YPipe当做写端,那么在另外一边就将其看成是读端。。。

这里的YPipe对象可以将其理解为队列,至于说具体的实现,底层确实是队列,只不过是自己实现的,而且实现的还挺繁琐的,就不细说了,不过这里有向吐槽的地方,明明concurrent库中有无锁的队列ConcurrentLinkedList,在并发环境下有很好的性能,干嘛不在这个基础上进行扩展。。。。

这里另外还要看看在ZeroMQ中,也定义的有Pipe类型自己的事件回调,其定义如下:

  1. public interface IPipeEvents {
  2. void read_activated(Pipe pipe);  //有数据可以读取
  3. void write_activated(Pipe pipe);  //当前pipe有数据写
  4. void hiccuped(Pipe pipe);   //对面的pipe替换掉了读端,也就是当前需要替换写段的时候的回调
  5. void terminated(Pipe pipe);  //当前pipe停止的回调
  6. }

具体每个方法是干嘛用的注释应该说的很清楚了。。那么接下来来看看Pipe的两端是怎么进行交互的吧,首先看如何发送数据到pipe的另外一端:

  1. //从写端写数据局,发送给pipe的另外一端
  2. public boolean write (Msg msg_)  {
  3. if (!check_write ())
  4. return false;
  5. boolean more = msg_.has_more();
  6. outpipe.write (msg_, more);
  7. if (!more)
  8. msgs_written++;   //已经读取的msg的计数
  9. return true;
  10. }

其实这里直接就是在写端,将数据写到队列里面去就好了,那么如何通知对面当前有数据发送过来了呢,来看另外一个方法:

  1. //其实这里主要是给对面的pipe发送activate_read命令,表示它可以读了
  2. public void flush () {
  3. //  The peer does not exist anymore at this point.
  4. if (state == State.terminating)
  5. return;
  6. if (outpipe != null && !outpipe.flush ()) {
  7. send_activate_read (peer);  //向对面发送可以读取的命令
  8. }
  9. }

这个,如果看了ZObject就应该很清楚了吧,直接给命令的另外一端发送activate_read类型的命令,那么这个命令最终将会被pipe的另外一端所关联的mailbox收到,从而对面的Pipe将会在其IO线程中执行命令,对于这个命令,进行的操作是process_activate_read方法,那么来看看Pipe中这个方法的的定义吧:

  1. //收到命令,表示底层的pipe有数据可以读取了,这里主要是要调用事件回调,通知上层的代码,pipe有数据可以读取了
  2. protected void process_activate_read () {
  3. if (!in_active && (state == State.active || state == State.pending)) {
  4. in_active = true;
  5. sink.read_activated (this);  //调用事件回调
  6. }
  7. }

这里其实就是调用当前的pipe的事件回调,来处理当前的pipe对象,其实也就是通知上层的代码,当前pipe有数据可以读了,让其进行处理。。。。

好了,那么到这里整个Pipe的运行原理就算比较的清楚了。。。

不过自己不太明白,在java中这种数据的传递明明很简单就可以实现,干嘛要搞的这么复杂。。。不过这里也有一个好处,就是将每一个对象的方法的执行都封闭在了自己的IO线程内部。。。也算是一种线程封闭原则的实现吧。。。其余的好处,好像没啥好处,而且真的觉得略繁琐。。。。

ZeroMQ(java)中组件间数据传输(Pipe的实现)的更多相关文章

  1. ZeroMQ(java)中的数据流SessionBase与SocketBase

    前面的文章中已经比较的清楚了ZeroMQ(java)中如何在底层处理IO, 通过StreamEngine对象来维护SelectableChannel对象以及IO的事件回调,然后通过Poller对象来维 ...

  2. ZeroMQ(JAVA)中的数据流,SessionBase与SocketBase

    前面的文章中已经比较的清楚了ZeroMQ(java)中如何在底层处理IO, 通过StreamEngine对象来维护SelectableChannel对象以及IO的事件回调,然后通过Poller对象来维 ...

  3. Vue中组件间通信的方式

    Vue中组件间通信的方式 Vue中组件间通信包括父子组件.兄弟组件.隔代组件之间通信. props $emit 这种组件通信的方式是我们运用的非常多的一种,props以单向数据流的形式可以很好的完成父 ...

  4. React中组件间通信的方式

    React中组件间通信的方式 React中组件间通信包括父子组件.兄弟组件.隔代组件.非嵌套组件之间通信. Props props适用于父子组件的通信,props以单向数据流的形式可以很好的完成父子组 ...

  5. ZeroMQ(java)中监控Socket

    基本上ZeroMQ(java)中基本的代码都算是过了一遍了吧,不过觉得它在日志这一块貌似基本没有做什么工作,也就是我们通过日志来知道ZeroMQ都发生了什么事情.. 而且由于ZeroMQ中将连接的建立 ...

  6. [转] React 中组件间通信的几种方式

    在使用 React 的过程中,不可避免的需要组件间进行消息传递(通信),组件间通信大体有下面几种情况: 父组件向子组件通信 子组件向父组件通信 跨级组件之间通信 非嵌套组件间通信 下面依次说下这几种通 ...

  7. React 中组件间通信的几种方式

    在使用 React 的过程中,不可避免的需要组件间进行消息传递(通信),组件间通信大体有下面几种情况: 父组件向子组件通信 子组件向父组件通信 非嵌套组件间通信 跨级组件之间通信 1.父组件向子组件通 ...

  8. Vue中组件间传值常用的几种方式

    版本说明: vue-cli:3.0 一.父子组件间传值 1.props/$emit -父组件==>>子组件: 子组件中通过定义props接收父组件中通过v-bind绑定的数据 父组件代码 ...

  9. Vue学习(二)-Vue中组件间传值常用的几种方式

    版本说明:vue-cli:3.0 主要分为两类: 1.父子组件间的传值 2.非父子组件间的传值 1.父子组件间传值 父组件向子组件传值 第一种方式: props 父组件嵌套的子组件中,使用v-bind ...

随机推荐

  1. [bzoj1296][SCOI2009]粉刷匠(泛化背包)

    http://www.lydsy.com:808/JudgeOnline/problem.php?id=1296 分析: 首先预处理出每一行的g[0..T]表示这一行刷0..T次,最多得到的正确格子数 ...

  2. CsharpThinking---代码契约CodeContract(八)

    代码契约(Code Contract):它并不是语言本身的新功能,而是一些额外的工具,帮助人们控制代码边界. 代码契约之于C#,就相当于诗词歌赋之于语言. --- C# in Depth 一,概述 1 ...

  3. EntityFramework_MVC4中EF5 新手入门教程之一 ---1.创建实体框架数据模型

    Contoso University  Web 应用程序 你会在这些教程中构建的应用程序是一个简单的大学网站. 用户可以查看和更新学生. 课程和教师信息.这里有几个屏幕,您将创建. 这个网站的用户界面 ...

  4. jQuery基础之(三)jQuery功能函数前缀及与window.onload冲突

    1.jQuery功能函数前缀 在javascript中,开发者通常会编写一些小函数来处理各种操作细节,例如在用户提交表单时,要将文本框最前端和最末端的空格内容清理掉.而javascript中没有类似t ...

  5. Java继承中属性、方法和对象的关系

    大家都知道子类继承父类是类型的继承,包括属性和方法!如果子类和父类中的方法签名相同就叫覆盖!如果子类和父类的属性相同,父类就会隐藏自己的属性! 但是如果我用父类和子类所创建的引用指向子类所创建的对象, ...

  6. 5.9-3 用正则表达式判断字符串text是否为合法的手机号

    package zfc; public class Zfc { public static void main(String[] args) { //判断手机号格式是否合法 String text = ...

  7. 嘻哈帮天通苑_poppin——张锋

    l click_me

  8. Java基础-内部类-为什么局部和匿名内部类只能访问局部final变量

    先看下面这段代码: public class Test { public static void main(String[] args) { } public void test(final int ...

  9. Java基础-数据类型int,short,char,long,float,double,boolean,byte

    Java语言是静态类型的(statical typed),也就是说所有变量和表达式的类型再编译时就已经完全确定.由于是statical typed,导致Java语言也是强类型(Strong typed ...

  10. Oracle之自定义函数

    数据库中函数包含四个部分:声明.返回值.函数体和异常处理. --没有参数的函数 create or replace function get_user return varchar2 is v_use ...