package com.ora.rmibook.chapter12.pool.thread2;
import com.ora.rmibook.chapter12.pool.*;
import java.util.*;
public class ThreadedPool2 implements Pool {
private int _maximumSize;
private Vector _availableObjects;
private int _totalNumberOfObjects;
private PoolHelper _helper;
private ObjectCreator _creator;
private ObjectReturner _returner;
public ThreadedPool2(String poolName, int maximumSize, PoolHelper helper) {
_maximumSize = maximumSize;
_helper = helper;
_availableObjects = new Vector();
startCreatorThread(poolName);
startReturnerThread(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;
}
private synchronized void waitForAvailableObject() {
try {
wait();
} catch (InterruptedException e) {/*ignored*/
}
}
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();
}
}
|