ODE Jacob 小解
Jacob (ODE Java Concurrent Objects)提供了一个应用级的并发机制(它并不是依赖于线程)同时包括一个透明的处理流程中断和持久化流程状态的机制。Jacob是Java对于ACTORS[Agha]并行模型实现的一个很大的组成部分,同时还有很多的流程代数学特征,像pi演算。本质上,Jacob提供了一个持久虚拟机来执行BPEL结构。
先看一个例子(Java工程结构如图一)
图一
第一步,定义一个接口 (Test.java):
package cn.qmwd.jacobTest;
import org.apache.ode.jacob.SynchChannel;
public interface Test {
public SynchChannel print(String str);
}
注意:这个接口中定义的方法必须是至少有一个参数,否则可能会出错。
第二步,再定义通道(Channel)接口(TestChannel.java):
package cn.qmwd.jacobTest;
import org.apache.ode.jacob.Channel;
public interface TestChannel extends Channel , Test {
}
第三步,定义通道监听器(ChannelListener)接口(TestChannelListener.java):
package cn.qmwd.jacobTest;
import org.apache.ode.jacob.ChannelListener;
public abstract class TestChannelListener extends ChannelListener<TestChannel> implements Test {
private static final long serialVersionUID = -1186997267517660170L;
protected TestChannelListener(TestChannel channel) throws IllegalStateException {
super(channel);
}
}
第四步,实现一个被调用(JacobRunnable的子类)类(TestObject.java):
package cn.qmwd.jacobTest;
import java.util.Date;
import org.apache.ode.jacob.JacobRunnable;
import org.apache.ode.jacob.SynchChannel;
public class TestObject extends JacobRunnable {
private static final long serialVersionUID = -8449707873233976113L;
private TestChannel channel;
public TestObject(TestChannel channel)
{
this.channel=channel;
}
@Override
public void run() {
object(true,new TestChannelListener(this.channel)
{
private static final long serialVersionUID = 6861624872661628447L;
@Override
public SynchChannel print(String str) {
System.out.println(new Date()+":"+str);
return null;
}
});
}
}
第五步,实现一个调用(JacobRunnable的子类)类(MainObject.java):
package cn.qmwd.jacobTest;
import org.apache.ode.jacob.JacobRunnable;
import org.apache.ode.jacob.SynchChannel;
import org.apache.ode.jacob.SynchChannelListener;
public class MainObject extends JacobRunnable {
private static final long serialVersionUID = 1L;
private String name=null;
public MainObject(String name)
{
this.name=name;
}
@Override
public void run() {
final TestChannel channel = newChannel(TestChannel.class);
instance(new TestObject(channel));
SynchChannel sc = channel.print(name + ":" + "1");
object(new SynchChannelListener(sc) {
private static final long serialVersionUID = -134980028995440578L;
@Override
public void ret() {
object(new SynchChannelListener(channel.print(name + ":" + "2")) {
private static final long serialVersionUID = -3593566527450652333L;
@Override
public void ret() {
object(new SynchChannelListener(channel.print(name + ":" + "3")) {
private static final long serialVersionUID = -3593566527450652333L;
@Override
public void ret() {
object(new SynchChannelListener(channel.print(name + ":" + "4")) {
private static final long serialVersionUID = -3593566527450652333L;
@Override
public void ret() {
object(new SynchChannelListener(channel.print(name + ":" + "5")) {
private static final long serialVersionUID = -3593566527450652333L;
@Override
public void ret() {
}
});
}
});
}
});
}
});
}
});
}
}
第六步,实现测试主类(Main.java)
package cn.qmwd.jacobTest;
import org.apache.ode.jacob.vpu.ExecutionQueueImpl;
import org.apache.ode.jacob.vpu.JacobVPU;
public class Main {
public static void main(String[] args) {
JacobVPU vpu=new JacobVPU(new ExecutionQueueImpl(null),new MainObject("Main 1"));
vpu.inject(new MainObject("Main 2"));
vpu.inject(new MainObject("Main 3"));
vpu.inject(new MainObject("Main 4"));
while(vpu.execute())
{
}
}
}
第七步,执行打印结果如下:
Mon Jan 11 12:21:23 CST 2010:Main 3:1
Mon Jan 11 12:21:23 CST 2010:Main 4:1
Mon Jan 11 12:21:23 CST 2010:Main 4:2
Mon Jan 11 12:21:23 CST 2010:Main 4:3
Mon Jan 11 12:21:23 CST 2010:Main 2:1
Mon Jan 11 12:21:23 CST 2010:Main 2:2
Mon Jan 11 12:21:23 CST 2010:Main 2:3
Mon Jan 11 12:21:23 CST 2010:Main 1:1
Mon Jan 11 12:21:23 CST 2010:Main 1:2
Mon Jan 11 12:21:23 CST 2010:Main 1:3
Mon Jan 11 12:21:23 CST 2010:Main 1:4
Mon Jan 11 12:21:23 CST 2010:Main 1:5
Mon Jan 11 12:21:23 CST 2010:Main 2:4
Mon Jan 11 12:21:23 CST 2010:Main 2:5
Mon Jan 11 12:21:23 CST 2010:Main 4:4
Mon Jan 11 12:21:23 CST 2010:Main 4:5
Mon Jan 11 12:21:23 CST 2010:Main 3:2
Mon Jan 11 12:21:23 CST 2010:Main 3:3
Mon Jan 11 12:21:23 CST 2010:Main 3:4
Mon Jan 11 12:21:23 CST 2010:Main 3:5
每次执行的结果不一定完全一样。但可以看出这4个实例是在交错执行,从用户角度看就是在并行,但是每个实例中的,打印顺序是依次递增的。
总结:
从上面的例子可以看出,ODE Jacob能够不依赖线程提供一个并发框架,并且提供同步机制。