Thinking in Java Ex35 [p1259]
Q. Modify BankTellerSimulation.java so that it represents Web clients making requests of a fixed number of servers. The goal is to determine the load that the group of servers can handle.
My solution:
Output:
Press ‘Enter’ to quit
[200][207][128][589][278][861][258][140][322][383][575][342][804][826][896][984][810][141][12][689] { T1 T0 }
[861][258][140][322][383][575][342][804][826][896][984][810][141][12][689][992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328] { T2 T0 T1 }
[826][896][984][810][141][12][689][992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552] { T3 T2 T1 T0 }
[992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552][244][111][934][843][585][966][615][913][921][213][409][983][158][225][326][851][198][505][332][310][933] { T4 T3 T1 T0 T2 }
[698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552][244][111][934][843][585][966][615][913][921][213][409][983][158][225][326][851][198][505][332][310][933][110][371][529][830][883][236][824][907][381][458][313][688][883][996][813][147][790][265][846][990][122] { T5 T3 T4 T0 T2 T1 }
Max Clients supported: 80
Q. Modify BankTellerSimulation.java so that it represents Web clients making requests of a fixed number of servers. The goal is to determine the load that the group of servers can handle.
My solution:
import java.util.concurrent.*; import java.util.*; //Read only objects don't require synchronization class Client { private final int serviceTime; public Client(int tm) { serviceTime = tm; } public int getServiceTime() { return serviceTime; } public String toString() { return "[" + serviceTime + "]"; } } //Teach the customer line to display itself: class ClientLine extends ArrayBlockingQueue<Client> { public ClientLine(int maxLineSize) { super(maxLineSize); } public String toString() { if (this.size() == 0) { return "[Empty]"; } StringBuilder result = new StringBuilder(); for (Client customer : this) { result.append(customer); } return result.toString(); } } //Randomly add customers to a queue: class ClientGenerator implements Runnable { private ClientLine customers; volatile int loadFactor = 1; //Start with one client/sec private static Random rand = new Random(47); public ClientGenerator(ClientLine cq) { customers = cq; } public void run() { try { while (!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(rand.nextInt(100)); customers.put(new Client(rand.nextInt(1000))); } } catch (InterruptedException e) { System.out.println("ClientGenerator interrupted"); } System.out.println("ClientGenerator terminating"); } } class Server implements Runnable, Comparable<Server> { private static int counter = 0; private final int id = counter++; //Clients served during this shift: private int customersServed = 0; private ClientLine customers; private boolean servingClientLine = true; public Server(ClientLine cq) { customers = cq; } public void run() { try { while (!Thread.interrupted()) { Client customer = customers.take(); TimeUnit.MILLISECONDS.sleep( customer.getServiceTime()); synchronized (this) { customersServed++; while (!servingClientLine) { wait(); } } } } catch (InterruptedException e) { System.out.println(this + "interrupted"); } System.out.println(this + "terminating"); } public synchronized void doSomethingElse() { customersServed = 0; servingClientLine = true; notifyAll(); } public synchronized void serveClientLine() { assert !servingClientLine : "already serving: " + this; servingClientLine = true; notifyAll(); } public String toString() { return "Server " + id + " "; } public String shortString() { return "T" + id; } // Used by priority queue: public synchronized int compareTo(Server other) { return customersServed < other.customersServed ? -1 : (customersServed == other.customersServed ? 0 : 1); } } class ServerManager implements Runnable { static int LIMIT = 0; private ExecutorService exec; private ClientLine customers; private PriorityQueue<Server> workingServers = new PriorityQueue<Server>(); private Queue<Server> tellersDoingOtherThings = new LinkedList<Server>(); private int adjustmentPeriod; private static Random rand = new Random(47); public ServerManager(ExecutorService e, ClientLine customers, int adjustmentPeriod) { exec = e; this.customers = customers; this.adjustmentPeriod = adjustmentPeriod; // Start with a single teller: Server teller = new Server(customers); exec.execute(teller); workingServers.add(teller); } public void adjustServerNumber() { // This is actually a control system. By adjusting // the numbers, you can reveal stability issues in // the control mechanism. // If line is too long, add another teller: if (customers.size() / workingServers.size() > 2) { // If tellers are on break or doing // another job, bring one back: if (tellersDoingOtherThings.size() > 0) { Server teller = tellersDoingOtherThings.remove(); teller.serveClientLine(); workingServers.offer(teller); return; } // Else create (hire) a new teller if(LIMIT<5){ Server teller = new Server(customers); exec.execute(teller); workingServers.add(teller); LIMIT++; return; } System.out.println("Max Clients supported: "+customers.size()); System.exit(0); return; } // If line is short enough, remove a teller: if (workingServers.size() > 1 && customers.size() / workingServers.size() < 2) { reassignOneServer(); } // If there is no line, we only need one teller: if (customers.size() == 0) { while (workingServers.size() > 1) { reassignOneServer(); } } } // Give a teller a different job or a break: private void reassignOneServer() { Server teller = workingServers.poll(); teller.doSomethingElse(); tellersDoingOtherThings.offer(teller); } public void run() { try { while (!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(adjustmentPeriod); adjustServerNumber(); System.out.print(customers + " { "); for (Server teller : workingServers) { System.out.print(teller.shortString() + " "); } System.out.println("}"); } } catch (InterruptedException e) { System.out.println(this + "interrupted"); } System.out.println(this + "terminating"); } public String toString() { return "ServerManager "; } } public class ServerSimulation { static final int MAX_LINE_SIZE = 1000; static final int ADJUSTMENT_PERIOD = 1000; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); // If line is too long, customers will leave: ClientLine customers = new ClientLine(MAX_LINE_SIZE); exec.execute(new ClientGenerator(customers)); // Manager will add and remove tellers as necessary: exec.execute(new ServerManager( exec, customers, ADJUSTMENT_PERIOD)); if (args.length > 0) // Optional argument { TimeUnit.SECONDS.sleep(new Integer(args[0])); } else { System.out.println("Press Enter to quit"); System.in.read(); } exec.shutdownNow(); } }
Output:
Press ‘Enter’ to quit
[200][207][128][589][278][861][258][140][322][383][575][342][804][826][896][984][810][141][12][689] { T1 T0 }
[861][258][140][322][383][575][342][804][826][896][984][810][141][12][689][992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328] { T2 T0 T1 }
[826][896][984][810][141][12][689][992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552] { T3 T2 T1 T0 }
[992][976][368][395][354][222][687][634][317][242][698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552][244][111][934][843][585][966][615][913][921][213][409][983][158][225][326][851][198][505][332][310][933] { T4 T3 T1 T0 T2 }
[698][899][665][909][209][158][273][894][984][533][8][328][779][882][37][871][17][828][696][994][419][738][434][106][718][965][416][217][677][146][552][244][111][934][843][585][966][615][913][921][213][409][983][158][225][326][851][198][505][332][310][933][110][371][529][830][883][236][824][907][381][458][313][688][883][996][813][147][790][265][846][990][122] { T5 T3 T4 T0 T2 T1 }
Max Clients supported: 80
No comments:
Post a Comment