FileDocCategorySizeDatePackage
ThreadedPool_Final.javaAPI DocExample4045Thu Nov 08 00:22:36 GMT 2001com.ora.rmibook.chapter12.pool.finalthread

ThreadedPool_Final.java

package com.ora.rmibook.chapter12.pool.finalthread;


import com.ora.rmibook.chapter12.pool.*;
import java.util.*;


public class ThreadedPool_Final implements Pool {
    private int _maximumSize;
    private int _steadyStateSize;
    private Vector _availableObjects;
    private int _totalNumberOfObjects;
    private PoolHelper _helper;
    private ObjectCreator _creator;
    private ObjectReturner _returner;
    private PoolShrinker _shrinker;

    public ThreadedPool_Final(String poolName, int steadyStateSize,
        int maximumSize, PoolHelper helper) {
        _steadyStateSize = steadyStateSize;
        _maximumSize = maximumSize;
        _helper = helper;
        _availableObjects = new Vector();
        startCreatorThread(poolName);
        startReturnerThread(poolName);
        startShrinkingThread(poolName);
    }

    public Object getObject() {
        Object returnValue = null;

        while (null == (returnValue = getLocallyAvailableObject())) {
            _creator.askForObject();
            waitForAvailableObject();
        }
        return returnValue;
    }

    public void returnObject(Object object) {
        _returner.validateAndReturn(object);
    }

    protected void returnObjectToPool(Object object) {
        if (_helper.isObjectStillValid(object)) {
            _availableObjects.add(object);
            notifyWaitingGets();
        } else {
            _helper.dispose(object);
            _totalNumberOfObjects--;
        }
        return;
    }

    protected void createAndAddObject() {
        Object createdObject = null;

        if (_totalNumberOfObjects < _maximumSize) {
            Object newObject = _helper.create();

            _availableObjects.add(newObject);
            _totalNumberOfObjects++;
        }
        if (null != createdObject) {
            notifyWaitingGets();
        }
        return;
    }

    protected void removeAnObject() {
        if (_totalNumberOfObjects < _steadyStateSize) {
            return;
        }
        Object objectToRemove = getLocallyAvailableObject();

        if (null != objectToRemove) {
            _helper.dispose(objectToRemove);
        }
    }
    
    private synchronized void waitForAvailableObject() {
        _shrinker.pause();	// if we have to wait, the pool is at full utilization
        try {
            wait();
        } catch (InterruptedException e) {/*ignored*/
        }
        _shrinker.resume();	// if we had to wait, the pool is at full utilization
    }

    private synchronized void notifyWaitingGets() {
        notify();
    }

    private Object getLocallyAvailableObject() {
        // Locks the container while we check for values.
        // That way, we don't simultaneously vend the same object
        // to two different requests
        synchronized (_availableObjects) {
            if (!_availableObjects.isEmpty()) {
                int lastPosition = _availableObjects.size() - 1;

                return _availableObjects.remove(lastPosition);
            }
        }
        return null;
    }

    private void startCreatorThread(String poolName) {
        _creator = new ObjectCreator(this);
        Thread creatorThread = new Thread(_creator, poolName + " creation thread");

        creatorThread.setPriority(Thread.NORM_PRIORITY - 2);
        creatorThread.start();
    }

    private void startReturnerThread(String poolName) {
        _returner = new ObjectReturner(this);
        Thread returnerThread = new Thread(_returner, poolName + " returner thread");

        returnerThread.setPriority(Thread.NORM_PRIORITY + 2);
        returnerThread.start();
    }

    private void startShrinkingThread(String poolName) {
        _shrinker = new PoolShrinker(this);
        Thread shrinkerThread = new Thread(_shrinker, poolName + " shrinking thread");

        shrinkerThread.setPriority(Thread.NORM_PRIORITY - 2);
        shrinkerThread.start();
    }
}