1. 对象池
当调用对象时,不使用常规的new 构造子的方式,而是通过一个对象池操作。
即如果池中存在该对象,则取出;如果不存在,则新建一个对象并存储在池中。当使用完该对象后,则将该对象的归还给对象池。
这里会存在几个问题,必须注意。
Tips 1,考虑多线程状态下的存取对象;
Tips 2,考虑将对象池目录表设计为Singleton模式,这样使得内存中仅存在唯一的一份缓存对象的表。
import java.util.ArrayList;
import java.util.List;
public class ObjectUnit<T> {
private Class<T> type;
private List<T> items = new ArrayList<T>();
private List<Boolean> checkedOut = new ArrayList<Boolean>();
private int semaphore;
public ObjectUnit(Class<T> type) {
this.type = type;
}
public synchronized T addItem() {
T obj;
try {
obj = type.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
items.add(obj);
checkedOut.add(false);
return obj;
}
public synchronized T checkOut() {
if (semaphore < items.size()) {
semaphore++;
return getItem();
} else
return addItem();
}
public synchronized void checkIn(T x) {
if (releaseItem(x))
semaphore--;
}
private synchronized T getItem() {
for (int index = 0; index < checkedOut.size(); index++)
if (!checkedOut.get(index)) {
checkedOut.set(index, true);
return items.get(index);
}
return null;
}
private synchronized boolean releaseItem(T item) {
int index = items.indexOf(item);
if (index == -1)
return false; // Not in the list
if (checkedOut.get(index)) {
checkedOut.set(index, false);
return true;
}
return false;
}
}
对象池目录表设计
使用
Map<Class<?>, ObjectUnit<?>>来保存当前对象池中类型目录,并把它设计为线程安全的
ConcurrentHashMap。
这里的getObj方法和renObj方法不用加锁,因为它调用的对象单元类是线程安全的,并且Map是线程安全的。
此外,这里在处理泛型的时候,会有warning产生,因为之前定义Map中使用<?>,而后面的两个泛型方法指定<T>。还没有想到更好的解决办法。
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Provider {
private Map<Class<?>, ObjectUnit<?>> providers = new ConcurrentHashMap<Class<?>, ObjectUnit<?>>();
private static Provider instance = new Provider();
private Provider() {
}
public static Provider getInstance() {
return instance;
}
@SuppressWarnings("unchecked")
public <T> T getObj(Class<T> key) {
ObjectUnit value = providers.get(key);
if (value != null) {
return (T) value.checkOut();
} else {
value = new ObjectUnit<T>(key);
providers.put(key, value);
return (T) value.addItem();
}
}
@SuppressWarnings("unchecked")
public <T> void renObj(T x) {
if (providers.containsKey(x.getClass())) {
ObjectUnit value = providers.get(x.getClass());
value.checkIn(x);
}
}
}
转载自:http://zhangjunhd.blog.51cto.com/113473/66059/
代码二:
public class ObjectPool {
private int numObjects = 10; // 对象池的大小
private int maxObjects = 50; // 对象池最大的大小
private Vector objects = null; //存放对象池中对象的向量( PooledObject类型)
public ObjectPool() {
}
/*** 创建一个对象池***/
public synchronized void createPool(){
// 确保对象池没有创建。如果创建了,保存对象的向量 objects 不会为空
if (objects != null) {
return; // 如果己经创建,则返回
}
// 创建保存对象的向量 , 初始时有 0 个元素
objects = new Vector();
// 根据 numObjects 中设置的值,循环创建指定数目的对象
for (int x = 0; x < numObjects; x++) {
if ((objects.size() == 0)&&this.objects.size() <this.maxObjects) {
Object obj = new Obj();
objects.addElement(new PooledObject(obj));
}
}
}
public synchronized Object getObject(){
// 确保对象池己被创建
if (objects == null) {
return null; // 对象池还没创建,则返回 null
}
Object conn = getFreeObject(); // 获得一个可用的对象
// 如果目前没有可以使用的对象,即所有的对象都在使用中
while (conn == null) {
wait(250);
conn = getFreeObject(); // 重新再试,直到获得可用的对象,如果
// getFreeObject() 返回的为 null,则表明创建一批对象后也不可获得可用对象
}
return conn;// 返回获得的可用的对象
}
/**
* 本函数从对象池对象 objects 中返回一个可用的的对象,如果
* 当前没有可用的对象,则创建几个对象,并放入对象池中。
* 如果创建后,所有的对象都在使用中,则返回 null
*/
private Object getFreeObject(){
// 从对象池中获得一个可用的对象
Object obj = findFreeObject();
if (obj == null) {
createObjects(incrementalObjects); //如果目前对象池中没有可用的对象,创建一些对象
// 重新从池中查找是否有可用对象
obj = findFreeObject();
// 如果创建对象后仍获得不到可用的对象,则返回 null
if (obj == null) {
return null;
}
}
return obj;
}
/**
* 查找对象池中所有的对象,查找一个可用的对象,
* 如果没有可用的对象,返回 null
*/
private Object findFreeObject(){
Object obj = null;
PooledObject pObj = null;
// 获得对象池向量中所有的对象
Enumeration enumerate = objects.elements();
// 遍历所有的对象,看是否有可用的对象
while (enumerate.hasMoreElements()) {
pObj = (PooledObject) enumerate.nextElement();
// 如果此对象不忙,则获得它的对象并把它设为忙
if (!pObj.isBusy()) {
obj = pObj.getObject();
pObj.setBusy(true);
}
return obj;// 返回找到到的可用对象
}
/**
* 此函数返回一个对象到对象池中,并把此对象置为空闲。
* 所有使用对象池获得的对象均应在不使用此对象时返回它。
*/
public void returnObject(Object obj) {
// 确保对象池存在,如果对象没有创建(不存在),直接返回
if (objects == null) {
return;
}
PooledObject pObj = null;
Enumeration enumerate = objects.elements();
// 遍历对象池中的所有对象,找到这个要返回的对象对象
while (enumerate.hasMoreElements()) {
pObj = (PooledObject) enumerate.nextElement();
// 先找到对象池中的要返回的对象对象
if (obj == pObj.getObject()) {
// 找到了 , 设置此对象为空闲状态
pObj.setBusy(false);
break;
}
}
}
/**
* 关闭对象池中所有的对象,并清空对象池。
*/
public synchronized void closeObjectPool() {
// 确保对象池存在,如果不存在,返回
if (objects == null) {
return;
}
PooledObject pObj = null;
Enumeration enumerate = objects.elements();
while (enumerate.hasMoreElements()) {
pObj = (PooledObject) enumerate.nextElement();
// 如果忙,等 5 秒
if (pObj.isBusy()) {
wait(5000); // 等 5 秒
}
// 从对象池向量中删除它
objects.removeElement(pObj);
}
// 置对象池为空
objects = null;
}
/**
* 使程序等待给定的毫秒数
*/
private void wait(int mSeconds) {
try {
Thread.sleep(mSeconds);
}
catch (InterruptedException e) {
}
}
/**
* 内部使用的用于保存对象池中对象的类。
* 此类中有两个成员,一个是对象,另一个是指示此对象是否正在使用的标志 。
*/
class PooledObject {
Object objection = null;// 对象
boolean busy = false; // 此对象是否正在使用的标志,默认没有正在使用
// 构造函数,根据一个 Object 构告一个 PooledObject 对象
public PooledObject(Object objection) {
this.objection = objection;
}
// 返回此对象中的对象
public Object getObject() {
return objection;
}
// 设置此对象的,对象
public void setObject(Object objection) {
this.objection = objection;
}
// 获得对象对象是否忙
public boolean isBusy() {
return busy;
}
// 设置对象的对象正在忙
public void setBusy(boolean busy) {
this.busy = busy;
}
}
}
测试类:
代码如下:
public class ObjectPoolTest {
public static void main(String[] args) throws Exception {
ObjectPool objPool = new ObjectPool();
objPool.createPool();
Object obj = objPool.getObject();
returnObject(obj);
objPool.closeObjectPool();
}
}
转自:http://blog.csdn.net/shimiso/article/details/9814917?utm_source=tuicool&utm_medium=referral
另外可参考:模拟数据库连接池 http://www.cnblogs.com/xinye/p/3907642.html