|
Distributed Computing ![]() This website demonstrates using wikis as teaching and learning tool. The course instructor is also happy to share the teaching materials here with those who find it readable. |
Tutorial /
Distributed Computing with Java RMIA Distributed Computing Tutorial by Steven Choy
IntroductionJava RMI provides a simple and direct model for distributed computing with Java objects. The objective of this tutorial is to allow you to practise programming RMI for distributed computing applications. Our main concern is on the programming aspect of distributing computing, not on the distributed computing problems themselves. Therefore, we select a fairly simple problem, rather than a good but complex one that can fully reveal the real power of distributing computing. You will apply the Java RMI system to implement a distributed computation of pi (π). Background KnowledgeComputation of pi:The application is to compute the value of pi (π) to the specified number of digits after the decimal point. For example, the following shows you the value of pi to 1000 decimal points: 3.141592653589793238462643383279502884197169399375105820974944592307816406286208 99862803482534211706798214808651328230664709384460955058223172535940812848111745 02841027019385211055596446229489549303819644288109756659334461284756482337867831 65271201909145648566923460348610454326648213393607260249141273724587006606315588 17488152092096282925409171536436789259036001133053054882046652138414695194151160 94330572703657595919530921861173819326117931051185480744623799627495673518857527 24891227938183011949129833673362440656643086021394946395224737190702179860943702 77053921717629317675238467481846766940513200056812714526356082778577134275778960 91736371787214684409012249534301465495853710507922796892589235420199561121290219 60864034418159813629774771309960518707211349999998372978049951059731732816096318 59502445945534690830264252230825334468503526193118817101000313783875288658753320 83814206171776691473035982534904287554687311595628638823537875937519577818577805 321712268066130019278766111959092164201989 One method to compute pi is to use Machin's formula: pi = 4‧ [4‧arctan(1/5) – arctan(1/239)] This method requires computation of arc tangent to sufficient precision. The following power series can be applied to compute the value of an arc tangent: arctan(x) = x – (x^3)/3 + (x^5)/5 + (x^7)/7 + (x^9)/9 + ... A class for computing arc tangent:To make use of the computation server, we create the following class for computing arc tangent to the specified number of digits after the decimal point. import java.math.*; public class InvArctan implements Softbot { private int inverseX; private int digits; private BigDecimal result; public InvArctan(int inverseX, int digits) { this.inverseX = inverseX; this.digits = digits; } public BigDecimal getResult() { return result; } public void execute() { BigDecimal ONE = BigDecimal.valueOf(1); BigDecimal ZERO = BigDecimal.valueOf(0); int roundingMode = BigDecimal.ROUND_HALF_EVEN; BigDecimal invX, invX2, numer, term; invX = BigDecimal.valueOf(inverseX); invX2 = BigDecimal.valueOf(inverseX * inverseX); numer = ONE.divide(invX, digits, roundingMode); result = numer; int i = 1; do { numer = numer.divide(invX2, digits, roundingMode); int denom = 2 * i + 1; term = numer.divide(BigDecimal.valueOf(denom), digits, roundingMode); if ((i % 2) != 0) { result = result.subtract(term); } else { result = result.add(term); } i++; } while (term.compareTo(ZERO) != 0); } } The following show you how to use this class to calculate the value of arctan(1/5) to 100 digits after the decimal point: InvArctan arctan1_5_object = new InvArctan(5,100); arctan1_5_object.execute(); BigDecimal arctan1_5 = arctan1_5_object.getResult(); Computation of pi with the InvArctan class:The following code shows you how to use InvArctan class to compute pi to 1000 (just an example) digits after the decimal point: // number of digits for pi int digits = 1000; // number of digits for arctan int scale = digits + 5; InvArctan a1_5 = new InvArctan(5,scale); InvArctan a1_239 = new InvArctan(239,scale); a1_5.execute(); a1_239.execute(); // Calculation of pi using Machin's formula BigDecimal arctan1_5 = a1_5.getResult(); BigDecimal arctan1_239 = a1_239.getResult(); BigDecimal ONE = BigDecimal.valueOf(1); BigDecimal ZERO = BigDecimal.valueOf(0); BigDecimal FOUR = BigDecimal.valueOf(4); BigDecimal pi = arctan1_5.multiply(FOUR).subtract(arctan1_239).multiply(FOUR); pi = pi.setScale(digits,BigDecimal.ROUND_HALF_UP); System.out.println(pi); Your TasksTask 1: Write the Remote InterfaceWrite a remote interface named import java.io.Serializable; public interface Softbot extends Serializable { public void execute(); } import java.rmi.Remote; import java.rmi.RemoteException; public interface RMIComputeEngine extends Remote { public Softbot getAndRunIt (Softbot sb) throws RemoteException; } Task 2: Write the Remote Object.Write a class named
import java.rmi.*; import java.rmi.server.*; public class RMIComputeEngineImpl extends UnicastRemoteObject implements RMIComputeEngine { public RMIComputeEngineImpl () throws RemoteException { } public Softbot getAndRunIt (Softbot sb) { sb.execute(); return sb; } public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "ComputeEngine"; try { RMIComputeEngineImpl computeEngine = new RMIComputeEngineImpl(); Naming.rebind(name, computeEngine); System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); } } } Task 3: Write the RMI ClientCreate a RMI client program for the computation of pi using the Machin's formula. Write a class named import java.rmi.*; import java.rmi.Naming; import java.math.*; public class RMIClient_ComputePi { public static void main (String[] args) throws Exception { int digits = 1000; if (args.length < 1) throw new IllegalArgumentException ("Syntax: RMIClient_ComputePi <hostname> <digits>"); if (args.length == 2) { try { digits = Integer.parseInt(args[1]); } catch (Exception ignore) { } } if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } RMIComputeEngine computeEngine = (RMIComputeEngine) Naming.lookup("//" + args[0] + "/ComputeEngine"); RMIComputeEngine computeEngine2 = (RMIComputeEngine) Naming.lookup("//" + args[0] + "/ComputeEngine"); int scale = digits + 5; InvArctan a1_5 = new InvArctan(5, scale); InvArctan a1_239 = new InvArctan(239, scale); a1_5 = (InvArctan)computeEngine.getAndRunIt(a1_5); a1_239 = (InvArctan)computeEngine2.getAndRunIt(a1_239); BigDecimal arctan1_5 = a1_5.getResult(); BigDecimal arctan1_239 = a1_239.getResult(); BigDecimal ONE = BigDecimal.valueOf(1); BigDecimal ZERO = BigDecimal.valueOf(0); BigDecimal FOUR = BigDecimal.valueOf(4); BigDecimal pi = arctan1_5.multiply(FOUR).subtract( arctan1_239).multiply(FOUR); pi = pi.setScale(digits,BigDecimal.ROUND_HALF_UP); System.out.println(pi); } } Compiling, Testing and Running
Path = C:\Program Files\Java\jdk1.5.0_08\bin set CLASSPATH=.;C:\Program Files\Java\jdk1.5.0_08\lib; javac *.java rmic RMIComputeEngineImpl
grant { permission java.net.SocketPermission "*:1024-65535", "connect,accept"; }; You can follow the following steps in testing your implemented components of distributed computation of pi.
Softbot.class, RMIComputeEngine.class, RMIComputeEngineImpl.class, InvArctan.class, java.policy
Softbot.class, RMIComputeEngine.class, InvArctan.class, RMIClient_ComputePi.class, RMIComputeEngineImpl_Stub.class, java.policy.
C:\mt368f\rmi\server>java -Djava.security.policy=java.policy RMIComputeEngineImpl
C:\mt368f\rmi\client>java -Djava.security.policy=java.policy RMIClient_ComputePi localhost More experiemnts
grant { permission java.net.SocketPermission "*:1024-65535", "connect,accept"; permission java.io.FilePermission "c:\\mt368f\\rmi\\client\\-", "read"; }; The above "java.policy" is used to specify that the server is allowed to automatically download any class file sit in the client side. In our application, the server needs to download InvArctan.class from the client side.
java -Djava.rmi.server.codebase=file:/c:\mt368f\rmi\client/ -Djava.security.policy=java.policy RMIClient_ComputePi localhost |