万能对象池【C#实现】
 

2009-02-27 作者:zhuweisky 来源:csdn

 

如果一种类型的对象需要经常被创建、销毁,为了提高性能,我们通常需要使用“池”技术,就如线程池、TCP连接池等一样。那么需要使用池技术的对象一般有哪些特征了?

(1)创建过程耗时

(2)不需要保存客户状态

(3)对象体积较大

(4)频繁创建/销毁

为了省事,我希望实现一个万能对象池组件,该对象池可以缓存任意类型的对象。下面给出对象池的接口:

public interface IObjectPool
    
{
        
//objType为缓存的对象的类型,cArgs为缓存对象的构造参数
        bool   Initialize(Type objType ,object[] cArgs ,int minNum ,int maxNum) ;
        
object RentObject() ;
        
void   GiveBackObject(int objHashCode) ;
        
void   Dispose() ;

        
int MinObjCount {get ;}
        
int MaxObjCount {get ;}
        
int CurObjCount {get ;}
        
int IdleObjCount {get ;}

        
event CallBackObjPool PoolShrinked  ;
        
event CallBackObjPool MemoryUseOut  ; //内存分配失败
    }


public delegate void CallBackObjPool() ;

上面接口中的各个方法的含义很清楚。其中PoolShrinked表示池中的对象个数有Max变为Min。

我们可以考虑这样一种情况,当我们需要缓存的对象需要维持和一个客户之间的状态,那么也是可以的,如果是这样,所缓存的类型最好实现下面的IPooledObjSupporter接口。

public interface IPooledObjSupporter : IDisposable
    
{
        
void Reset() ; //恢复对象为初始状态,当IObjectPool.GiveBackObject时调用
    }

对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:

using System;
using System.Collections ;
using System.Reflection;

namespace EnterpriseServerBase.Infrastructure
{
    
/// <summary>
    
/// IObjectPool 的默认实现。
    
/// 作者:朱伟 sky.zhuwei@163.com 
    
/// </summary>

    #region ObjectPool
    
public class ObjectPool :IObjectPool 
    
{
        
#region members
        
private Type destType = null ;
        
private object[] ctorArgs = null ;
        
private int minObjCount = 0 ;
        
private int maxObjCount = 0 ;
        
private int shrinkPoint = 0 ;
        
private Hashtable hashTableObjs   = new Hashtable() ;
        
private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle        其中key就是hashcode
        private ArrayList keyList = new ArrayList() ;
        
private bool supportReset = false ;
        
#endregion


        
#region IObjectPool 成员
        
public event CallBackObjPool PoolShrinked ;    
        
public event CallBackObjPool MemoryUseOut ;

        
public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
        
{
            
if(minNum < 1)
            
{
                minNum = 1 ;
            }

            
if(maxNum < 5)
            
{
                maxNum = 5 ;
            }


            
this.destType = objType ;
            
this.ctorArgs = cArgs ;
            
this.minObjCount = minNum ;
            
this.maxObjCount = maxNum ;
            
double cof = 1 - ((double)minNum /(double)maxNum) ;
            
this.shrinkPoint = (int)(cof * minNum) ;

            
//缓存的类型是否支持IPooledObjSupporter接口
            Type supType = typeof(IPooledObjSupporter) ;
            
if(supType.IsAssignableFrom(objType))
            
{
                
this.supportReset = true ;
            }


            
this.InstanceObjects() ;

            
return true ;
        }


        
private void InstanceObjects()
        
{
            
for(int i=0 ;i<this.minObjCount ;i++)
            
{
                
this.CreateOneObject() ;
            }

        }


        
#region CreateOneObject ,DistroyOneObject
        
private int CreateOneObject()
        
{
            
object obj = null ;

            
try
            
{
                obj = Activator.CreateInstance(
this.destType ,this.ctorArgs) ;
            }

            
catch(Exception ee) //分配内存失败!
            {
                ee = ee ;
                
this.maxObjCount = this.CurObjCount ;
                
if(this.minObjCount > this.CurObjCount)
                
{
                    
this.minObjCount = this.CurObjCount ;
                }


                
if(this.MemoryUseOut != null)
                
{
                    
this.MemoryUseOut() ;
                }


                
return -1 ;
            }


            
int key = obj.GetHashCode() ;
            
this.hashTableObjs.Add(key ,obj) ;
            
this.hashTableStatus.Add(key ,true ) ;
            
this.keyList.Add(key) ;

            
return key ;
        }


        
private void DistroyOneObject(int key)
        
{
            
object target = this.hashTableObjs[key] ;
            IDisposable tar = target 
as IDisposable ;
            
if(tar != null)
            
{
                tar.Dispose() ;
            }


            
this.hashTableObjs.Remove(key) ;
            
this.hashTableStatus.Remove(key) ;
            
this.keyList.Remove(key) ;
        }

        
#endregion


        
public object RentObject()
        
{
            
lock(this)
            
{
                
object target = null ;
                
foreach(int key in this.keyList)
                
{
                    
if((bool)this.hashTableStatus[key]) //isIdle
                    {
                        
this.hashTableStatus[key] = false ;
                        target = 
this.hashTableObjs[key] ;
                        
break ;
                    }

                }


                
if(target == null)
                
{
                    
if(this.keyList.Count < this.maxObjCount)
                    
{
                        
int key = this.CreateOneObject() ;
                        
if(key != -1)
                        
{
                            
this.hashTableStatus[key] = false ;
                            target = 
this.hashTableObjs[key] ;
                        }

                    }

                }


                
return target ;
            }

            
        }


        
#region GiveBackObject
        
public void GiveBackObject(int objHashCode)
        
{
            
if(this.hashTableStatus[objHashCode] == null)
            
{
                
return ;
            }


            
lock(this)
            
{
                
this.hashTableStatus[objHashCode] = true ;
                
if(this.supportReset) 
                
{
                    IPooledObjSupporter supporter = (IPooledObjSupporter)
this.hashTableObjs[objHashCode] ;
                    supporter.Reset() ;
                }


                
if(this.CanShrink())
                
{
                    
this.Shrink() ;
                }

            }

        }


        
//能够收缩对象池
        private bool CanShrink()
        
{
            
int idleCount = this.GetIdleObjCount() ;    
            
int busyCount = this.CurObjCount - idleCount ;

            
return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount + (this.maxObjCount - this.minObjCount)/2)) ;
        }

        
        
private void Shrink()
        
{
            
while(this.CurObjCount > this.minObjCount)
            
{
                
int destKey = -1 ;
                
foreach(int key in this.keyList)
                
{
                    
if((bool)this.hashTableStatus[key])
                    
{
                        destKey = key ;
                        
break ;
                    }

                }


                
if(destKey != -1)
                
{
                    
this.DistroyOneObject(destKey) ;
                }

                
else
                
{
                    
break ;
                }

            }


            
if(this.PoolShrinked != null)
            
{
                
this.PoolShrinked() ;
            }

        }

        
#endregion


        
public void Dispose()
        
{
            Type supType = 
typeof(System.IDisposable) ;
            
if(supType.IsAssignableFrom(this.destType))
            
{
                ArrayList list = (ArrayList)
this.keyList.Clone() ;
                
foreach(int key in list)
                
{
                    
this.DistroyOneObject(key) ;
                }

            }


            
this.hashTableStatus.Clear() ;
            
this.hashTableObjs.Clear() ;
            
this.keyList.Clear() ;
        }
        

        
#region property
        
public int MinObjCount
        
{
            
get
            
{
                
return this.minObjCount ;
            }

        }


        
public int MaxObjCount
        
{
            
get
            
{
                
return this.maxObjCount ;
            }

        }


        
public int CurObjCount
        
{
            
get
            
{
                
return this.keyList.Count ;
            }

        }


        
public int IdleObjCount
        
{
            
get
            
{
                
lock(this)
                
{
                    
return this.GetIdleObjCount() ;
                }

            }

        }


        
private int GetIdleObjCount()
        
{
            
int count = 0 ;
            
foreach(int key in this.keyList)
            
{
                
if((bool)this.hashTableStatus[key])
                
{
                    ++ count ;
                }

            }


            
return count ;
        }

        
#endregion


        
#endregion

    }

    
#endregion

}

 

对象在实现该接口后,就可以被对象池在收到归还的对象时重置其状态了。整个对象池的实现代码如下:

using System;
using System.Collections ;
using System.Reflection;

namespace EnterpriseServerBase.Infrastructure
{
    
/// <summary>
    
/// IObjectPool 的默认实现。
    
/// 作者:朱伟 sky.zhuwei@163.com 
    
/// </summary>

    #region ObjectPool
    
public class ObjectPool :IObjectPool 
    
{
        
#region members
        
private Type destType = null ;
        
private object[] ctorArgs = null ;
        
private int minObjCount = 0 ;
        
private int maxObjCount = 0 ;
        
private int shrinkPoint = 0 ;
        
private Hashtable hashTableObjs   = new Hashtable() ;
        
private Hashtable hashTableStatus = new Hashtable() ; //key - isIdle        其中key就是hashcode
        private ArrayList keyList = new ArrayList() ;
        
private bool supportReset = false ;
        
#endregion


        
#region IObjectPool 成员
        
public event CallBackObjPool PoolShrinked ;    
        
public event CallBackObjPool MemoryUseOut ;

        
public bool Initialize(Type objType, object[] cArgs, int minNum, int maxNum)
        
{
            
if(minNum < 1)
            
{
                minNum = 1 ;
            }

            
if(maxNum < 5)
            
{
                maxNum = 5 ;
            }


            
this.destType = objType ;
            
this.ctorArgs = cArgs ;
            
this.minObjCount = minNum ;
            
this.maxObjCount = maxNum ;
            
double cof = 1 - ((double)minNum /(double)maxNum) ;
            
this.shrinkPoint = (int)(cof * minNum) ;

            
//缓存的类型是否支持IPooledObjSupporter接口
            Type supType = typeof(IPooledObjSupporter) ;
            
if(supType.IsAssignableFrom(objType))
            
{
                
this.supportReset = true ;
            }


            
this.InstanceObjects() ;

            
return true ;
        }


        
private void InstanceObjects()
        
{
            
for(int i=0 ;i<this.minObjCount ;i++)
            
{
                
this.CreateOneObject() ;
            }

        }


        
#region CreateOneObject ,DistroyOneObject
        
private int CreateOneObject()
        
{
            
object obj = null ;

            
try
            
{
                obj = Activator.CreateInstance(
this.destType ,this.ctorArgs) ;
            }

            
catch(Exception ee) //分配内存失败!
            {
                ee = ee ;
                
this.maxObjCount = this.CurObjCount ;
                
if(this.minObjCount > this.CurObjCount)
                
{
                    
this.minObjCount = this.CurObjCount ;
                }


                
if(this.MemoryUseOut != null)
                
{
                    
this.MemoryUseOut() ;
                }


                
return -1 ;
            }


            
int key = obj.GetHashCode() ;
            
this.hashTableObjs.Add(key ,obj) ;
            
this.hashTableStatus.Add(key ,true ) ;
            
this.keyList.Add(key) ;

            
return key ;
        }


        
private void DistroyOneObject(int key)
        
{
            
object target = this.hashTableObjs[key] ;
            IDisposable tar = target 
as IDisposable ;
            
if(tar != null)
            
{
                tar.Dispose() ;
            }


            
this.hashTableObjs.Remove(key) ;
            
this.hashTableStatus.Remove(key) ;
            
this.keyList.Remove(key) ;
        }

        
#endregion


        
public object RentObject()
        
{
            
lock(this)
            
{
                
object target = null ;
                
foreach(int key in this.keyList)
                
{
                    
if((bool)this.hashTableStatus[key]) //isIdle
                    {
                        
this.hashTableStatus[key] = false ;
                        target = 
this.hashTableObjs[key] ;
                        
break ;
                    }

                }


                
if(target == null)
                
{
                    
if(this.keyList.Count < this.maxObjCount)
                    
{
                        
int key = this.CreateOneObject() ;
                        
if(key != -1)
                        
{
                            
this.hashTableStatus[key] = false ;
                            target = 
this.hashTableObjs[key] ;
                        }

                    }

                }


                
return target ;
            }

            
        }


        
#region GiveBackObject
        
public void GiveBackObject(int objHashCode)
        
{
            
if(this.hashTableStatus[objHashCode] == null)
            
{
                
return ;
            }


            
lock(this)
            
{
                
this.hashTableStatus[objHashCode] = true ;
                
if(this.supportReset) 
                
{
                    IPooledObjSupporter supporter = (IPooledObjSupporter)
this.hashTableObjs[objHashCode] ;
                    supporter.Reset() ;
                }


                
if(this.CanShrink())
                
{
                    
this.Shrink() ;
                }

            }

        }


        
//能够收缩对象池
        private bool CanShrink()
        
{
            
int idleCount = this.GetIdleObjCount() ;    
            
int busyCount = this.CurObjCount - idleCount ;

            
return (busyCount < this.shrinkPoint) && (this.CurObjCount > (this.minObjCount + (this.maxObjCount - this.minObjCount)/2)) ;
        }

        
        
private void Shrink()
        
{
            
while(this.CurObjCount > this.minObjCount)
            
{
                
int destKey = -1 ;
                
foreach(int key in this.keyList)
                
{
                    
if((bool)this.hashTableStatus[key])
                    
{
                        destKey = key ;
                        
break ;
                    }

                }


                
if(destKey != -1)
                
{
                    
this.DistroyOneObject(destKey) ;
                }

                
else
                
{
                    
break ;
                }

            }


            
if(this.PoolShrinked != null)
            
{
                
this.PoolShrinked() ;
            }

        }

        
#endregion


        
public void Dispose()
        
{
            Type supType = 
typeof(System.IDisposable) ;
            
if(supType.IsAssignableFrom(this.destType))
            
{
                ArrayList list = (ArrayList)
this.keyList.Clone() ;
                
foreach(int key in list)
                
{
                    
this.DistroyOneObject(key) ;
                }

            }


            
this.hashTableStatus.Clear() ;
            
this.hashTableObjs.Clear() ;
            
this.keyList.Clear() ;
        }
        

        
#region property
        
public int MinObjCount
        
{
            
get
            
{
                
return this.minObjCount ;
            }

        }


        
public int MaxObjCount
        
{
            
get
            
{
                
return this.maxObjCount ;
            }

        }


        
public int CurObjCount
        
{
            
get
            
{
                
return this.keyList.Count ;
            }

        }


        
public int IdleObjCount
        
{
            
get
            
{
                
lock(this)
                
{
                    
return this.GetIdleObjCount() ;
                }

            }

        }


        
private int GetIdleObjCount()
        
{
            
int count = 0 ;
            
foreach(int key in this.keyList)
            
{
                
if((bool)this.hashTableStatus[key])
                
{
                    ++ count ;
                }

            }


            
return count ;
        }

        
#endregion


        
#endregion

    }

    
#endregion

}

 

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织