分布式计算的第一次课,法师给了几份代码,要求仔细阅读后理解代码,为接下来的进一步学习做准备。代码涉及到的应该都是分布式计算的基础,相信接下来的开发会用到,这里先做一下总结。代码总共涉及到以下五个方面:
这方面的内容相信写过java代码的人都知道了,Java采用将出错处理和正常代码分开的方法来实现异常处理。每当Java程序运行过程中发生一个可识别的运行错误时,即该错误有一个异常类与之相对应时,系统都会产生一个相应的该异常类的对象,即产生一个异常。一旦一个异常对象产生了,系统中就一定有相应的机制来处理它,确保不会产生死机、死循环或其他对操作系统的损害,从而保证了整个程序运行的安全性。
// 捕获与处理异常例程 class Account { private double balance = 1000; public void transfer(double amount)throws OutOfMoney { // 在方法中声明抛出异常 if (balance < amount) // 直接抛出异常 throw new OutOfMoney("[Balance:" + balance + " < Amount:" + amount + "]"); balance = balance - amount; } public double getBalance() { return balance; } } class OutOfMoney extends Exception { public OutOfMoney() { // 给出该异常的一个缺省的字符串描述 super("Your account have not enough money!"); } public OutOfMoney(String msg) { // 允许使用者自行给出对异常的一个字符串描述 super(msg); } } public class AccountException { public static void main(String[]args) { Account obj = new Account(); double amount = 800; for (int count = 0; count < 3; count++) { try { obj.transfer(amount); System.out.println("Transfer amount: " + amount + ", and then balance: " + obj.getBalance()); } catch (OutOfMoney exc) { exc.printStackTrace(); } finally { System.out.println("finally语句块中的语句总是会执行!"); } amount = amount - 300; } } }
// 简单的利用流套接字实现通信的服务端程序 import java.io.*; import java.net.*; public class MyServer { public static void main(String[] args)throws IOException { if (args.length != 1) { System.out.println("用法:EchoServer <端口号>"); return ; } // 创建 ServerSocket 实例,建立连接 ServerSocket server = new ServerSocket(Integer.parseInt(args[0])); System.out.println("服务程序正在监听端口" + args[0]); // 监听客户程序的连接请求 Socket client = server.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out = new PrintWriter(client.getOutputStream()); // 从客户端读取数据,并打印在屏幕上,如果接收到”End”,则退出程序。 String str; System.out.println("客户端已经建立连接"); while ((str = in.readLine()) != null) { System.out.println(str); System.out.println("收到请求:" + str); out.println("服务端已经收到请求:" + str); out.flush(); if (str.equals("end")) { System.out.println("通信已经终止"); break; } } // 关闭连接 out.close(); in.close(); client.close(); } }
// 简单的利用流套接字实现通信的客户端程序 import java.net.*; import java.io.*; public class MyClient { static Socket server; public static void main(String[] args)throws Exception { if (args.length != 2) { System.out.println("用法:MyClient <主机名> <端口号>"); return ; } // 获取本地ip地址,访问在本地的服务程序,缺省端口是:1234 Socket server = new Socket(args[0], Integer.parseInt(args[1])); // 建立连接并打开相关联的输入流和输出流 BufferedReader in = new BufferedReader(new InputStreamReader (server.getInputStream())); PrintWriter out = new PrintWriter(server.getOutputStream()); BufferedReader wt = new BufferedReader(new InputStreamReader(System.in)); // 将控制台输入的字符串发送给服务端,如果接收到"end",则退出程序。 while (true) { String str = wt.readLine(); out.println(str); out.flush(); if (str.equals("end")) { System.out.println("通信已经终止"); break; } System.out.println(in.readLine()); } // 关闭连接 wt.close(); out.close(); in.close(); server.close(); } }
两个小例子,代码很简单,分别是通过实现Runnable接口定义新线程以及通过继承thread类定义新线程。
// 通过实现Runnable接口定义新线程 class Counter implements Runnable { public void run() { for (int i = 0; i < 100; i++) System.out.println("计数器= " + i); } } public class RunnableThread { public static void main(String[] args) { Counter counter = new Counter(); Thread thread = new Thread(counter); thread.start(); System.out.println("主程序结束"); } }
// 通过继承Thread类定义新线程 public class SubclassThread extends Thread { public void run() { while (true) { // 执行线程自身的任务 try { sleep(5 * 1000); break; } catch (InterruptedException exc) { // 睡眠被中断 } } } public static void main(String[] args) { Thread thread = new SubclassThread(); thread.start(); System.out.println("主程序结束"); } }
无论是何种类型的数据,都是以二进制序列的形式在网络上传送,所以需要发送进程将对象转换为字节序列,才能在网络上传送;接收进程则需要把字节序列再恢复为对象。在进程间消息通信过程中,把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。因此,对象的序列化主要有两种用途:将对象的字节序列持久化,保存在文件系统中;在网络上传送对象的字节序列。
// 测试对象的序列化和反序列化 import java.io.*; public class AccountSerializable { public static void main(String[] args)throws Exception { // 创建本地文件输入流 File f = new File("objectFile.obj"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); // 序列化对象 Account Account1 = new Account("Zhang3", 1000); Account Account2 = new Account("Li4", 2000); out.writeObject(Account1); out.writeObject(Account2); out.close(); // 反序列化对象 ObjectInputStream in = new ObjectInputStream(new FileInputStream(f)); Account obj1 = (Account)in.readObject(); System.out.println("Account1=" + obj1); Account obj2 = (Account)in.readObject(); System.out.println("Account2=" + obj2); in.close(); } } // Account类实现java.io.Serializable接口 class Account implements Serializable { private String name; private double balance; public Account(String name, double balance) { this.name = name; this.balance = balance; } public String toString() { return "name=" + name + ", balance=" + balance; } }
java语言的反射机制:
Java语言的反射(Reflection)机制可以在程序运行时判断任意一个对象所属的类,构造任意一个类的对象,判断任意一个类所具有的成员变量和方法,调用任意一个对象的方法,或者生成动态代理。
// 演示Reflection的基本使用方法 import java.lang.reflect.*; public class AccountReflect { public Object copy(Object object)throws Exception { // 获得对象的类型 Class classType = object.getClass(); System.out.println("Class:" + classType.getName()); // 通过默认构造方法创建一个新的对象 Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{}); // 获得对象的所有属性 Field fields[] = classType.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String fieldName = field.getName(); String firstLetter = fieldName.substring(0,1).toUpperCase(); // 获得和属性对应的getXXX()方法的名字 String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字 String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法 Method getMethod = classType.getMethod(getMethodName, new Class[]{}); // 获得和属性对应的setXXX()方法 Method setMethod = classType.getMethod(setMethodName, new Class[] {field.getType()}); // 调用原对象的getXXX()方法 Object value = getMethod.invoke(object, new Object[]{}); System.out.println(fieldName + ":" + value); // 调用复制对象的setXXX()方法 setMethod.invoke(objectCopy, new Object[]{value}); } return objectCopy; } public static void main(String[] args)throws Exception { Account Account = new Account("Zhang3", 1000); Account AccountCopy = (Account)new AccountReflect().copy(Account); System.out.println("Copy information:" + AccountCopy.getName() + " " + AccountCopy.getBalance()); } } // Account类 class Account { private String name; private int balance; public Account(){} public Account(String name, int balance) { this.name = name; this.balance = balance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } }
//远程对象接口 public interface AccountService { public String getAccount(String Name); }
//远程对象接口的实现类 public class AccountServiceImpl implements AccountService { public String getAccount(String Name) { return "Account id: " + Name; } }
//远程调用对象 import java.io.*; public class RemoteCall implements Serializable { private String className; //表示类名或接口名 private String methodName; //表示方法名 private Class[] paramTypes; //表示方法参数类型 private Object[] params; //表示方法参数值 //表示方法的执行结果 //如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。 private Object result; public RemoteCall(){} public RemoteCall(String className, String methodName, Class[] paramTypes, Object[] params) { this.className = className; this.methodName = methodName; this.paramTypes = paramTypes; this.params = params; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Class[] getParamTypes() { return paramTypes; } public void setParamTypes(Class[] paramTypes) { this.paramTypes = paramTypes; } public Object[] getParams() { return params; } public void setParams(Object[] params) { this.params = params; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; } public String toString() { return "className=" + className + " methodName=" + methodName; } }
// 客户端程序 import java.io.*; import java.net.*; import java.util.*; public class RemoteClient { public void invoke()throws Exception { Socket socket = new Socket("localhost", 8000); OutputStream out = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); InputStream in = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(in); RemoteCall call = new RemoteCall("AccountService", "getAccount", new Class[] { String.class }, new Object[] {"Zhang3"}); // 向服务器发送Call 对象 oos.writeObject(call); // 接收包含了方法执行结果的Call 对象 call = (RemoteCall)ois.readObject(); System.out.println(call.getResult()); ois.close(); oos.close(); socket.close(); } public static void main(String args[])throws Exception { new RemoteClient().invoke(); } }
//服务端程序 import java.io.*; import java.net.*; import java.util.*; import java.lang.reflect.*; public class Server { // 存放远程对象的缓存 private Map remoteObjects = new HashMap(); // 把一个远程对象放到缓存中 public void register(String className, Object remoteObject) { remoteObjects.put(className, remoteObject); } public void service()throws Exception { // 创建基于流的Socket,并在8000端口监听 ServerSocket serverSocket = new ServerSocket(8000); System.out.println("服务器启动......"); while (true) { Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(in); OutputStream out = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); RemoteCall remotecallobj = (RemoteCall)ois.readObject(); //接收客户发送的Call对象 System.out.println(remotecallobj); remotecallobj = invoke(remotecallobj); //调用相关对象的方法 oos.writeObject(remotecallobj); //向客户发送包含了执行结果的remotecallobj对象 ois.close(); oos.close(); socket.close(); } } public RemoteCall invoke(RemoteCall call) { Object result = null; try { String className = call.getClassName(); String methodName = call.getMethodName(); Object[] params = call.getParams(); Class classType = Class.forName(className); Class[] paramTypes = call.getParamTypes(); Method method = classType.getMethod(methodName, paramTypes); Object remoteObject = remoteObjects.get(className); //从缓存中取出相关的远程对象 if (remoteObject == null) { throw new Exception(className + "的远程对象不存在"); } else { result = method.invoke(remoteObject, params); } } catch (Exception e) { result = e; } call.setResult(result); //设置方法执行结果 return call; } public static void main(String args[])throws Exception { Server server = new Server(); //把事先创建的RemoteServiceImpl 对象加入到服务器的缓存中 server.register("AccountService", new AccountServiceImpl()); server.service(); } }