在上部分的介绍中,已经可以直接使用Jchannel构建一个简单的组通信,接下来将介绍一些在编程中比较常用的类和接口。
一、基本接口:以下类位于org.jgroups包下
1)MessageListener:消息监听器
以下内容为程序代码:
public interface MessageListener { void receive(Message msg); byte[] getState(); void setState(byte[] state); }
|
|
2)ExtendedMessageListener:扩展消息监听器
以下内容为程序代码:
public interface ExtendedMessageListener extends MessageListener { byte[] getState(String state_id); void setState(String state_id, byte[] state); }
|
|
3)MemberShipListener:成员监听器
以下内容为程序代码:
public interface MembershipListener { void viewAccepted(View new_view); void suspect(Object suspected_mbr); void block(); }
|
|
4)ChannelListener:通道监听器
以下内容为程序代码:
public interface ChannelListener { void channelConnected(Channel channel); void channelDisconnected(Channel channel); void channelClosed(Channel channel); void channelShunned(); void channelReconnected(Address addr); }
|
|
5)Receiver:接受者
以下内容为程序代码:
public interface Receiver extends MessageListener, MembershipListener { }
|
|
6)ExtendedReceiver:扩展接受者
以下内容为程序代码:
public interface ExtendedReceiver extends ExtendedMessageListener, MembershipListener { }
|
|
示例如下:
以下内容为程序代码:
JChannel ch=new JChannel(); ch.setReceiver(new ExtendedReceiverAdapter() { public void receive(Message msg) { System.out.println("received message " + msg); } public void viewAccepted(View new_view) { System.out.println("received view " + new_view); } }); ch.connect("bla"[img]/images/wink.gif[/img];
|
|
在通道同时担当接受者和发送者时需要创建至少两个线程分担两个不同的工作,通过向Jchannel注册一个接受者(Receiver),使我们不需要自己显式地创建接受线程
二、高层组件:以下类位于org.jgroups.blocks包下
使用JavaGroups的基本接口和通道编程比较直接而直观,缺点是编程有时过于繁杂,JavaGroups为我们提供了一些高层的组件降低编程的难度。(以下类位于org.jgroups.blocks包下)
1.拉推模式适配器(PullPushAdapter)
一般直接使用Jchannel,是采用拉的方式,即用户自己编程去“推动”接收和发送信息,通过该适配器,即转换为由用户注册一个Listener,由适配器去“推动“接收和发送信息,例:
以下内容为程序代码:
public class PullPushTest implements MessageListener { Channel channel; PullPushAdapter adapter; byte[] data="Hello world".getBytes(); public void receive(Message msg) { System.out.println("Received msg: " + msg); } public void start() throws Exception { channel=new JChannel(); channel.connect("PullPushTest"[img]/images/wink.gif[/img]; adapter=new PullPushAdapter(channel); adapter.setListener(this); for(int i=0; i < 10; i++) { System.out.println("Sending msg #" + i); channel.send(new Message(null, null, data)); Thread.currentThread().sleep(1000); } adapter.stop(); channel.close(); } public static void main(String args[]) { try { new PullPushTest().start(); } catch(Exception e) { /* error */ } } }
|
|
2.信息分发器(MessageDispatcher)
Jchannel是采用异步的方式接受信息的,如果想使用同步接受信息,可使用该类,当然,该类也可用于异步接受信息,由于该类内部使用了PullPushAdapter,所以其也是“推“模式。例见下:
以下内容为程序代码:
public class MessageDispatcherTest implements RequestHandler { Channel channel; MessageDispatcher disp; RspList rsp_list; public void start() throws Exception { channel=new JChannel(); disp=new MessageDispatcher(channel, null, null, this); channel.connect("MessageDispatcherTestGroup"[img]/images/wink.gif[/img]; for(int i=0; i < 10; i++) { Thread.sleep(100); System.out.println("Casting message #" + i); rsp_list=disp.castMessage(null, new Message(null, null, new String("Number #" + i)), GroupRequest.GET_ALL, 0);//GET_ALL表示等待所有信息发完 System.out.println("Responses:\n" +rsp_list); } channel.close(); disp.stop(); } public Object handle(Message msg) { System.out.println("handle(): " + msg); return new String("Success !"[img]/images/wink.gif[/img]; } public static void main(String[] args) { try { new MessageDispatcherTest().start(); } catch(Exception e) { System.err.println(e); } } }
|
|
看看每次操作的返回结果RspList类的声明
以下内容为程序代码:
public class RspList { public boolean isReceived(Address sender); public int numSuspectedMembers(); public Vector getResults(); public Vector getSuspectedMembers(); public boolean isSuspected(Address sender); public Object get(Address sender); public int size(); public Object elementAt(int i) throws ArrayIndexOutOfBoundsException; } 其保存了每条信息的操作结果情况 3.RPC分发器(RpcDispatcher) RPC用户远程与本地相同的对象的方法调用,见下面例子: [code] public class RpcDispatcherTest { Channel channel; RpcDispatcher disp; RspList rsp_list; public int print(int number) throws Exception { return number * 2; } public void start() throws Exception { channel=new JChannel(props); disp=new RpcDispatcher(channel, null, null, this); channel.connect("RpcDispatcherTestGroup"[img]/images/wink.gif[/img]; for(int i=0; i < 10; i++) { Thread.sleep(100); rsp_list=disp.callRemoteMethods(null, "print", new Integer(i), GroupRequest.GET_ALL, 0); System.out.println("Responses: " +rsp_list); } channel.close(); disp.stop(); } public static void main(String[] args) { try { new RpcDispatcherTest().start(); } catch(Exception e) { System.err.println(e); } } }
|
|
三、分布式数据结构:
使用分布式数据结构可以在多个进程的内部保持数据结构的多个实例,在任何时刻每个实例都有相同的值,主要有DistributedHashtable、ReplicatedHashtable和DistributedTree,其使用比较直接,此处不再做详细举例
参考:《JGroups文档》