基于反射机制的数据流Java多态性实现及研究
2010-08-23曹大有
曹大有
CAO Da-you
(郧阳师范高等专科学校 计算机科学系,丹江口 442700)
1 数据流Java 程序设计模型[3]
1.1 传统数据流模型
数据流模型很早就被提了出来,一般一个数据流程序由多个actor 组成。传统的细粒度数据流模型中,actor 的粒度是一个操作,而在粗粒度的数据流模型中,actor 的粒度可以是一个函数。actor 之间只能通过先入先出的缓冲队列进行通信。每个actor有一个相应的触发规则(firing rule)集合,当其中某一规则满足时,该actor被触发,读取输入队列上的数据,产生输出数据。actor 是没有内部状态的,它的行为只由输入数据和触发规则决定。类似的模型还有进程网络(process network)。每个进程是一小段串行程序,进程之间只能通过先入先出的缓冲队列进行同步和通信。当一个进程读一个空队列或者写一个满队列时,它会被阻塞,直到操作完成。
1.2 数据流Java[1,3]
在数据流和进程网络模型中,各个运行单元之间的同步和通信是通过显式的数据传递来完成的。由于禁止了运行单元之间的隐式数据共享,避免了多线程模型的数据竞争和冲突,有利于程序的形式化分析和验证。数据流模型能够帮助程序员自然地表达应用程序的内部并行性,减少编译器并行化分析和优化的难度。
数据流Java中最小的独立运行的单元叫做组件(component),它对应于我们通常的进程或线程。组件内只能串行执行。一个数据流 Java 程序可以拥有多个组件,各个组件之间可以独立运行。
组件可以定义自己的输入和输出端口(port),用于和外部通信。组件之间的显式数据通信只能通过输入和输出端口之间进行。通信时数据对象的发送和接收是异步的、先入先出的。当某个组件通过一个输出端口对多个组件的普通输入端口发送数据对象时,可以有两种发送方式:将数据对象复制多个副本后发送到所有组件;或者以轮转方式依次发送。如果是对多个组件的参数端口发送数据对象,那么也可以有两种方式:将数据对象的引用发送给所有组件共享;或者以复制的方式发送。数据流 Java 采用隐式多线程模型,程序员需要知道组件运行时可能有多个副本同时运行。如果访问参数端口传递的共享的数据对象,则需要保证操作是原子的。
2 基于反射机制的数据流Java多态性实现
反射是指一个系统表述和改变自身行为的能力[2],反射机制允许程序运行时动态地加载一个类,生成该对象的实例和调用该实例的方法。下面我们就以数据流多态例,利用Java提供的反射机制来实现数据流Java的多态性。
设计出Java的类Shape、Rectangle和Triangle。然后针对类继承体系中的每一个类设计出对应的数据流Java的组件类,以类Rectangle为例,对应的数据流Java的组件类为:
下面我们就要来研究如何利用Java语言提供的反射机制来实现数据流Java多态性的组件类,该组件类类名我们就命名为PolymorphismComponent。由于在该类体系中每个类只有一个构造方法且该构造方法有两个double型的参数,所以对组件类PolymorphismComponent的输入参数类型设为形如"12.3,45.6,Shape"的String类型,其中12.3,45.6为构造方法提供参数,Shape为具体类名。
在组件类PolymorphismComponent的execute()方法中,首先通过输入端口的receive()方法接收数据,然后分离出需要动态加载的类名classStr,再通过以下过程:
来动态生成对象obj,其中parts[0]和parts[1]为构造方法的参数.对象obj生成后,再通过以下条件语句进行数据的发送:
上面的条件语句实际上是在组件类PolymorphismComponent中维护了一个称之为分派树(dispatch tree)的数据结构,分派树在运行时构建网络的时候创建。输入端口类型必须是输出端口类型本身或者其子类,一个类型只允许有一个端口。运行时,系统根据类的层次关系建立一个反向的树结构。树的每个节点记录它的类型和对应的出口。输出端口在发送数据对象时,根据分派树从上向下进行匹配,然后向匹配的端口进行发送。这样该组件类的主要逻辑就设计好了,至于一个输入端口可在@InPort()中设计完成,多个输出端口可在@OutPorts()中设计完成,最后通过方法openPorts()打开即可。
测试工作可在Network类的define()方法中完成.先用component()方法给组件类命名:
然后用connect()方法进行组件类之间的连接:
最后用initialize()方法给组件类Polymorphism Component提供初始参数:
由于初始参数中指定的类名为Shape,所以输出的是Shape的面积;当将类名换为Rectangle,输出的是Rectangle的面积;当将类名换为Triangle,输出的是Triangle的面积.
若现在要增设Circle类,只需为Circle类开发一个对应的组件类Circle Component,然后在Network类的define()方法中加上以下语句即可:
再在由条件语句组成的称之为分派树的数据结构加上对Circle类对象实例的判断即可,这样当将initialize()方法中的类名换为Circle,输出的是Circle的面积。
3 结束语
本文通过Java语言提供的反射机制和类动态加载机制实现了数据流Java多态性的并行程序设计模型,并通过实例对该模型进行了验证.从实现的过程中可以看出:该过程具有一定的通用性和实用性,有利于数据流Java程序的并行性和模块化.实现的重点是称之为分派树的数据结构.
[1]刘弢,范彬,吴承勇,张兆庆.数据流 Java 并行程序设计模型的设计、实现及运行时优化[J].软件学报,2009,19(9):2184-2185.
[2]程峰,黄若波,章恒翀.Java2核心技术卷I:基础知识[M].北京:机械工业出版社,2004:158-190.
[3]Flow·based programming[EB/OL].http://www.Jpaulmorrison.corn/fbp/.