Load-Balancing Classes Load Balancing

- 225 -

10.8.2 Load-Balancing Classes

If you need to implement your own queuing system, you have to consider whether the queue controls the request processors, or whether the processors access the queue. The latter model is how the socket model works: each request processor sits on the queue and waits for it to pass a request. This looks rather like the following class: public class PassiveRequestQueue { The queue of requests FIFO_Queue queue = new FIFO_Queue ; public synchronized void acceptRequestRequest r { Add to the queue, then notify all processors waiting on the releaseRequest method queue.addr; notify ; } public synchronized Request releaseRequest { for;; { if the queue is empty, just go back into the wait call if queue.isEmpty try {wait ;} catch InterruptedException e{} Need to check again if the queue is empty, in case we were interrupted if queue.isEmpty return Request queue.pop ; } } } The former model, in which the request processors are passive and the queue actively manages them, looks more like the following class: public class ActiveRequestQueue subclass the passive queue which holds the behavior needed for managing the queue of requests extends PassiveRequestQueue and make us able to run in our own thread implements Runnable { int MAXIMUM_NUM_SERVERS=3; Data for the public queue - a list of private servers ActiveRequestQueue[] servers; Data for the private internal queues the RequestProcessor RequestProcessor requestProcessor; Retain a handle on my thread so that we can easily access it if we need control Thread myThread; Keep a handle on the public queue - the one which actually holds the objects ActiveRequestQueue queueServer; Availability boolean isAvailable = true; - 226 - Internal queue object - processes requests private ActiveRequestQueueActiveRequestQueue q { queueServer = q; requestProcessor=new RequestProcessor ; } External queue object - accepts requests and manages a queue of them public ActiveRequestQueueint num_servers { Create a pool of queue servers and start them in their own threads servers = new ActiveRequestQueue[num_servers]; Thread t; for int i = servers.length-1; i=0 ; i-- { servers[i] = new ActiveRequestQueuethis; t = new Threadservers[i].start ; servers[i].myThread = t; } } public synchronized void acceptRequestRequest r { Override the super class accept to increase the number of servers if they are all busy If we already have the maximum number of threads, just queue the request if servers.length = MAXIMUM_NUM_SERVERS { super.acceptRequestr; return; } otherwise, if one of the servers is available, just queue the request for int i = servers.length-1; i=0 ; i-- { if servers[i].isAvailable { super.acceptRequestr; return; } } otherwise, increase the server pool by one, then queue the request Thread t; ActiveRequestQueue[] tmp_servers = servers; servers = new ActiveRequestQueue[tmp_servers.length+1]; System.arraycopytmp_servers, 0, servers, 0, tmp_servers.length; servers[tmp_servers.length] = new ActiveRequestQueuethis; t = new Threadservers[tmp_servers.length].start ; servers[tmp_servers.length].myThread = t; super.acceptRequestr; } public void run { Request request; RequestResult result; Private queues use this method. - 227 - Basically, we just ask the public server for a request. The releaseRequest method blocks until one is available. Then we process it and start again. for;; { request = queueServer.releaseRequest ; isAvailable = false; result = requestProcessor.processRequestrequest; returnResultresult; isAvailable = true; } } public boolean isAvailable { return isAvailable;} public void returnResultRequestResult r {} } Note that the server classes as they stand can be tested with the following minimal implementations for support classes: class FIFO_Queue { java.util.Stack v = new java.util.Stack ; public void addObject o{v.pusho;} public Object pop {return v.pop ;} public boolean isEmpty {return v.isEmpty ;} } class RequestProcessor { public RequestResult processRequestRequest r { System.out.printlnProcessing request: + r; try{Thread.sleep2000;}catchInterruptedException e{} return new RequestResult ; } } class RequestResult {} class Request {}

10.8.3 A Load-Balancing Example