class ClientImplementation extends NetworkPeer implements Client, Runnable { int id; synchronized public void setID(Integer index) { this.id = index.intValue(); } Client[] peer = new Client[100]; int index = -1; synchronized public void register(Integer index, Client client) { this.index = index.intValue(); this.peer[this.index] = client; } Boolean available = new Boolean(true); synchronized public void setAvailable(Boolean availability) { this.available = availability; } int balance; public int getBalance() { return this.balance; } String name; public String report() { return this.name + ": " + this.balance; } public ClientImplementation(String name) { this.name = name; } public void startAsClientOf(java.rmi.Remote peer) throws java.rmi.RemoteException { Server server = (Server)peer; server.register(this); this.server = server; new Thread(this).start(); } Server server; public void run() { while (true) { try { Thread.sleep((int) Math.random() * 1000 + 1000); if (this.available.booleanValue()) this.initiateTransfer(); } catch (Exception e) { } } } synchronized private void initiateTransfer() throws java.rmi.RemoteException { if (this.index > 0) { int chosen = (int) (Math.random() * (this.index + 1)); if (chosen == this.id // always deal with someone else || peer[chosen] == null) return; System.out.println(this.id + " chooses " + chosen); this.balance += peer[chosen].process( new Transaction( this.name, this.id, (int)(Math.random() * 10 + 1), Math.random() > 0.5 ? "sent" : "requested")); } } synchronized public int process(Transaction transaction) throws java.rmi.RemoteException { if (this.available.booleanValue()) { this.balance = transaction.update(this); if (transaction.direction.equals("sent")) { return - (transaction.amount); } else { return (transaction.amount); } } else return 0; // object unavailable: method idempotent } public static void main(String[] args) throws Exception { String ownName = args[0], serverHostName = args[1], serverPortNumber = args[2], serverName = args[3]; ClientImplementation client = new ClientImplementation(ownName); client.startAsNetworkClientOf(serverHostName, Integer.parseInt(serverPortNumber), serverName); } public void startAsLocalServer() { // not needed, a client is an anonymous figure, a guest without a permanent address ... } }