实现高效的数据库连接池(附带完整代码Csharp和Java实现)_第1页
实现高效的数据库连接池(附带完整代码Csharp和Java实现)_第2页
实现高效的数据库连接池(附带完整代码Csharp和Java实现)_第3页
实现高效的数据库连接池(附带完整代码Csharp和Java实现)_第4页
实现高效的数据库连接池(附带完整代码Csharp和Java实现)_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、相关技术:· 连接池 · 引用记数 · 多线程 · C#.Net · Java 适宜人群· 数据库应用程序程序员 · 系统分析员 · 模块设计师 · 有一定功底的程序员 目录· 引言 1. 数据库连接池(Connection Pool)的工作原理 · 连接池关键问题分析 1. 并发问题 2. 事务处理 3. 连接池的分配与释放 4. 连接池的配置与维护 · 关键议题1. 引用记数2. 如何实现事务处理3.  管理连接池· 结合代码说明1. 构造方法2. 启

2、动服务StartService3. 停止服务StopService4. 申请 GetConnectionFormPool5. 释放DisposeConnection6. 如何更新属性7. 如何确定连接是否失效8. 使用线程管理连接池1. threadCreate2. threadCheck9.  其他引言一般的数据库应用程序大致都遵循下面的步骤:1. 初始化程序 2. 用户在UI上输入操作 3. 由用户操作产生数据库操作 4. 将数据库操作递交到数据库服务器 5. . (重复24) 6. 关闭应用程序 而本文则着重讲解上面第4步骤.在着一步骤中我们经常是,打开数据库连接操作

3、数据库,最后关闭数据库.在服务器端程序设计上与数据库的操作显得十分重要,因为你要处理的数据操作十分巨大.如果频繁创建数据库连接频繁关闭数据库连接则会引起效率低下甚至引发程序崩溃. 也许我们可以有另一种操作数据库的形式,我们可以在程序运行时打开一个数据库连接,让这个连接永久存在直到程序'死亡',那么这样做也有不安全隐患,我 们知道一个对象存在时间越长或被使用次数越多则它表现的越不稳定,着不稳定因素是由于对象内部可能存在的潜在设计问题产生,对于数据库连接对象道理也一 样.我们不能保证一个Connection对象里面能一点问题不存在.所以我们也不敢长时间将它长时间占用内存.既然有这么

4、多的问题由此我们需要一个能帮我们维护数据库连接的东西-它就是连接池,网上有很多的连接池例子,但是多数都是简单的例子,或者介绍比较复杂的连接池原理,没有一个比较完整介绍和实现连接池的例子.这里就介绍你如何自己制作一个连接池. 对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配释放所造成的问题。为解决我们的问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连 接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设 定连接池最大连接数来防

5、止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量使用情况,为系统开发测试及性能 调整提供依据。连接池的基本工作原理见下图。数据库连接池(Connection Pool)的工作原理 连接池关键问题分析1、并发问题为了使连接管理服务具有最大的通用 性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为各个语言自身提供了对并发管理的支持像java,c#等等,使用 synchronized(java)lock(C#)关键字即可确保线程是同步的。使用方法可以参考,相关文献。、事务处理我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-

6、ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。 我们知道当个线程公用一个连接Connection对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使 Connection类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有个线程都在进行事务操作而引起的。 为此我们可以使用每一个事务独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性。、连接池的分配与释放连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加

7、快用户的访问速度。对于连接的管理可使用一个List。即把已经创建的连接都放入List中去统一管理。每当用户请求一个连接时,系统检查这个List中有没有可以分配的连接。如果有就把那个最合适的连接分配给他(如何能找到最合适的连接文章将在关键议题中指出);如果没有就抛出一个异常给用户,List中连接是否可以被分配由一个线程来专门管理捎后我会介绍这个线程的具体实现。  、连接池的配置与维护连接池中到底应该放置多少连接,才 能使系统的性能最佳?系统可采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接。 比方说,最小连接数是系统启

8、动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快, 响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数 是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过软件需求上得到。如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。 关键议题· 引用记数在分配、释放

9、策略对 于有效复用连接非常重要,我们采用的方法也是采用了一个很有名的设计模式:Reference Counting(引用记数)。该模式在复用资源方面用的非常广泛,我们把该方法运用到对于连接的分配释放上。每一个数据库连接,保留一个引用记数,用来 记录该连接的使用者的个数。具体的实现上,我们对Connection类进行进一步包装来实现引用记数。被包装的Connection类我们提供个方法 来实现引用记数的操作,一个是Repeat(被分配出去)Remove(被释放回来);然后利用RepeatNow属性来确定当前被引用多少,具体是哪个 用户引用了该连接将在连接池中登记;最后提供IsRepeat属性来确

10、定该连接是否可以使用引用记数技术。一旦一个连接被分配出去,那么就会对该连接的申 请者进行登记,并且增加引用记数,当被释放回来时候就删除他已经登记的信息,同时减少一次引用记数。这样做有一个很大的好处,使得我们可以高效的使用连接,因为一旦所有连接都被分配出去,我们就可以根据相应的策略从使用池中挑选出一个已经正在使用的连接用来复用,而不是随意拿出一个连接去复用。策略可以根据需要去选择,我们有策略可是使用:.ConnLevel_ReadOnly独占方式 使用空闲的实际连接分配连接资源,并且在该资源释放回之前,该资源在连接池中将不能将其引用分配给其他申请者。如果连接池中所有实际连接资源都已经分配 出去,

11、那么即使连接池可以在分配引用资源在该模式下连接迟将不会分配连接资源,连接池会产生一个异常,标志连接池资源耗尽。例:假如一个实际连接可以被分配5次,那么使用该模式申请连接的话您将损失4个可分配的连接,只将得到一个连接资源。 直至该资源被释放回连接池,连接池才继续分配它剩余的4次机会。 当你在使用连接时可能应用到事务时,可以使用该模式的连接,以确定在事务进行期间您可以对该连接具有独享权限,以避免各个数据库操作访问的干扰。.ConnLevel_High优先级-高使用空闲的实际连接分配连接资源,并且在该资源释放回之前,该资源在连接池中将可能将其引用分配给其他申请者。*注意:此级别不保证在分配该资源后,

12、仍然保持独立占有连接资源,若想独立占有资源请使用ReadOnely, 因为当连接池达到某一时机时该资源将被重复分配(引用记数)然而这个时机是不可预测的。如果您申请的连接会用于事务处理您可以使用ConnLevel_ReadOnly级别。.ConnLevel_None优先级-中适当应用引用记数技术分配连接资源。在该模式下,连接池内部会按照实际连接已经使用次数排序(多->少),然后在结果中选取 1/3 位置的连接资源返回。与优先级-高相同该模式也不具备保持独立占有连接资源的特性。如果您申请的连接会用于事务处理您可以使用ConnLevel_ReadOnly级别。.ConnLevel_Bottom

13、优先级-底尽 可能使用引用记数技术分配连接。在该模式下,连接池内部会按照实际连接已经使用次数排序(多->少),然后在结果中选取被使用最多的返回。该模式适 合处理较为不重要的连接资源请求。与优先级-高相同该模式也不具备保持独立占有连接资源的特性。如果您申请的连接会用于事务处理您可以使用ConnLevel_ReadOnly级别。以上4条策略选自datebasepool_SDK(datebasepool是本文所开发的最终产物)· 如何实现事务处理 前面谈到的都是关于使用数据库连 接进行普通的数据库访问。对于事务处理,情况就变得比较复杂。因为事务本身要求原子性的保证,此时就要

14、求对于数据库的操作符合"All-All- Nothing"原则,即要么全部完成,要么什么都不做。如果简单的采用上述的连接复用的策略,就会发生问题,因为没有办法控制属于同一个事务的多个数据 库操作方法的动作,可能这些数据库操作是在多个连接上进行的,并且这些连接可能被其他非事务方法复用。Connection本身具有提供了对 于事务的支持,具体实现方法请参看Connection的msdn,显式的调用commit或者rollback方法来实现。但是要安全、高效的进行 Connection进行复用,就必须提供相应的事务支持机制。我们采用的方法是:用户以ConnLevel_ReadOn

15、ly模式申请一个连接之后该连接就由该申请者独自享有该连接,具体事务操作由用户自行设计编写,连接池只提供用户独自占有。·  管理连接池在上文中我们说过这个连接池内部连接管理使用的是独立的线程来 工作(threadCreate和threadCheck)threadCreate线程负责创建连接 ,threadCheck线程负责检查每个连接是 否达到自己的寿命,标志连接寿命的条件是被引用的次数超过它最大被引用次数,或者达到最大生存时间。这些参数都由ConnStruct类管 理,ConnStruct类是包装连接的类,下面定义的就是连接池使用到的属性变量(C#代码) 

16、;       /属性        private int _realFormPool;/连接池中存在的实际连接数(包含失效的连接)        private int _potentRealFormPool;/连接池中存在的实际连接数(有效的实际连接)      

17、  private int _spareRealFormPool;/空闲的实际连接        private int _useRealFormPool;/已分配的实际连接        private int _readOnlyFormPool;/连接池已经分配多少只读连接       

18、; private int _useFormPool;/已经分配出去的连接数        private int _spareFormPool;/目前可以提供的连接数        private int _maxConnection;/最大连接数,最大可以创建的连接数目        

19、private int _minConnection;/最小连接数        private int _seepConnection;/每次创建连接的连接数        private int _keepRealConnection;/保留的实际空闲连接,以攻可能出现的ReadOnly使用,当空闲连接不足该数值时,连接池将创建seepConnection个连接 

20、       private int _exist = 20;/每个连接生存期限 20分钟        private int _maxRepeatDegree = 5;/可以被重复使用次数(引用记数),当连接被重复分配该值所表示的次数时,该连接将不能被分配出去        

21、/当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力        private DateTime _startTime;/服务启动时间        private string _connString = null;/连接字符串        

22、private ConnTypeEnum _connType;/连接池连接类型        private PoolState _ps;/连接池状态        /内部对象        private ArrayList al_All = new ArrayLis

23、t();/实际连接        private Hashtable hs_UseConn = new Hashtable();/正在使用的连接        private System.Timers.Timer time;/监视器记时器        private Thre

24、ad threadCreate;/创建线程        private bool isThreadCheckRun = false;Java版本    /属性    private int _RealFormPool; /连接池中存在的实际连接数(包含失效的连接)    private int _

25、PotentRealFormPool; /连接池中存在的实际连接数(有效的实际连接)    private int _SpareRealFormPool; /空闲的实际连接    private int _UseRealFormPool; /已分配的实际连接    private int _ReadOnlyFormPool; /连接池已经分配多少只读连接  

26、  private int _UseFormPool; /已经分配出去的连接数    private int _SpareFormPool; /目前可以提供的连接数    private int _MaxConnection; /最大连接数,最大可以创建的连接数目    private int _MinConnection; /最小连接数

27、    private int _SeepConnection; /每次创建连接的连接数    private int _KeepRealConnection; /保留的实际空闲连接,以攻可能出现的ReadOnly使用,当空闲连接不足该数值时,连接池将创建seepConnection个连接    private int _Exist = 20; /每个连接生存期限&#

28、160;20分钟    private String _userID=""    private String _password=""    /可以被重复使用次数(引用记数),当连接被重复分配该值所表示的次数时,该连接将不能被分配出去    /当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力 &

29、#160;  private int _MaxRepeatDegree = 5;    private Date _StartTime; /服务启动时间    private String _ConnString = null; /连接字符串    private String _DriveString =&

30、#160;null; /驱动字符串    private int _PoolState; /连接池状态    /内部对象    private ArrayList al_All = new ArrayList(); /实际连接    private Hashtable hs_UseConn = ne

31、w Hashtable(); /正在使用的连接    private CreateThreadProcess threadCreate;    private CheckThreadProcess threadCheck; 当用户调用连接池的StartService方法时,在 StartService方法中会通知threadCreate线程创建静态连接,然后将这些静态连接加入到List,同时启动threadCheck线 程,threadCheck

32、线程负责检测List中的最小空闲连接是否少于连接池配置的最少空闲连接数,当条件为真时threadCheck线程会负责再 次唤醒threadCreate线程同时给threadCreate线程传递这次要创建的连接个数。对于threadCreate线程有种工作模式,模式为初始化创建模式,该模式会创建连接迟池配置的最小连接数目;模式即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接时的工作模式。申请连接,当用户申请连接时必须指定一个发起者和一个申请优先级别,优先级由ConnLevel_*系列指定。一旦用户从连接池中申请到一个连接时就将申请到的连接引用和申请者,同时

33、加入到HashTable来注册到连接池。释放连接,将注册的用户删除。   下面是代码说明共有Java和C#个版本,版本可能捎有不同因为各个语言有自己的特点Java版本的构造方法    public ConnectionPool() .        InitConnectionPool("", "", 200, 30, 10, 5);&#

34、160;       public ConnectionPool(String connectionString, String driveString) .        InitConnectionPool(connectionString, driveString, 200, 30, 10, 5);   

35、0;    public ConnectionPool(String connectionString, String driveString, int maxConnection, int minConnection) .        InitConnectionPool(connectionString, driveString, maxConnection,&

36、#160;minConnection, 10, 5);        public ConnectionPool(String connectionString, String driveString, int maxConnection, int minConnection, int seepConnection, int keepRealConnection) .

37、        InitConnectionPool(connectionString, driveString, maxConnection, minConnection, seepConnection, keepRealConnection);    C#版本的构造方法        public ConnectionPool(str

38、ing connectionString)        . InitConnectionPool(connectionString, ConnTypeEnum.Odbc, 200, 30, 10, 5, 5);         public ConnectionPool(string connectionString,

39、0;ConnTypeEnum cte)        . InitConnectionPool(connectionString, cte, 200, 30, 10, 5, 5);         public ConnectionPool(string connectionString, ConnTypeEnum&#

40、160;cte, int maxConnection, int minConnection)        . InitConnectionPool(connectionString, cte, maxConnection, minConnection, 10, 5, 5);         public C

41、onnectionPool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection)        . InitConnectionPool(connectionString, cte, maxC

42、onnection, minConnection, seepConnection, keepConnection, 5);         public ConnectionPool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConn

43、ection, int keepConnection, int keepRealConnection)        . InitConnectionPool(connectionString, cte, maxConnection, minConnection, seepConnection, keepConnection, keepRealConnection); 上面个版本的构造方法都调用I

44、nitConnectionPool方法,下面是InitConnectionPool方法实现(C#)          /*/ <summary>        / 初始化函数    / </summary>        protected vo

45、id InitConnectionPool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection, int keepRealConnection)        .  

46、60;         if (cte = ConnTypeEnum.None)                throw new ConnTypeExecption();/参数不能是None         

47、   _ps = PoolState.UnInitialize;            this._connString = connectionString;            this._connType = cte;   

48、0;        this._minConnection = minConnection;            this._seepConnection = seepConnection;            this._keepRe

49、alConnection = keepRealConnection;            this._maxConnection = maxConnection;            this.time = new System.Timers.Timer(500); 

50、0;          this.time.Stop();            this.time.Elapsed += new System.Timers.ElapsedEventHandler(time_Elapsed);          &

51、#160; this.threadCreate = new Thread(new ThreadStart(createThreadProcess);         在InitConnectionPool方法中我们定义了连接池要连接的数据库类型ConnTypeEnum cte,和连接字符串string connectionString等类型,在方法最后注册了Timer类的Elapsed 事件,在C#版中Timer类就充当threadCh

52、eck线程,而Elapsed事件就是线程threadCheck的执行方法体。由于刚刚初始化连接池对象故threadCheck线程不需要运行所以在InitConnectionPool方法中将Timer关闭。下面是java实现:       private void InitConnectionPool(String connectionString, String driveString, int maxConnection, int m

53、inConnection, int seepConnection, int keepRealConnection) .        this._PoolState = PoolState_UnInitialize;        this._ConnString = connectionString;    

54、;    this._DriveString = driveString;        this._MinConnection = minConnection;        this._SeepConnection = seepConnection;       &

55、#160;this._KeepRealConnection = keepRealConnection;        this._MaxConnection = maxConnection;        this.threadCheck = new CheckThreadProcess();      &#

56、160; this.threadCheck.setDaemon(true);        this.threadCreate = new CreateThreadProcess();        this.threadCreate.setDaemon(true);        this.threadCheck.s

57、tart();    while(threadCheck.getState()!=Thread.State.WAITING).    由于Java中的Timer类需要 AWT 的GUI线程组建支持,总不能在我们的连接池中开辟一个Form出来把,因此在Java版本中使用线程来实现Timer,在Java版本中 threadCheck一开始就被启动,然后又等待threadCheck线程自己被阻塞又是为什么呢,这样做是为了实现C#版本中stop方法.(由于 个人原因这个连接池最初是由C#.Net2.0开发而成的故而在Jav

58、a中可能存在许多设计不合理)。由上面代码可以看出一旦连接池被创建出来以后就已经运行了一个threadCheck线程(对于Java版),而这个线程将立刻进入WAITING等待状态。  启动服务StartService        /*/ <summary>        / 启动服务,线程安全        /

59、60;</summary>        public void StartServices()        .            lock (this)          

60、;  .                createThreadMode = 0;/工作模式0                createThreadProcessRun = true;   

61、;             createThreadProcessTemp = _minConnection;                if (_ps = PoolState.UnInitialize)    &#

62、160;               threadCreate.Start();                else if (_ps = PoolState.Stop)      

63、60;             threadCreate.Interrupt();                else               

64、0;    throw new PoolNotStopException();/服务已经运行或者未完全结束                time.Start();                  

65、  createThreadMode 是设置threadCreate的工作模式为创建模式,前面我们说过threadCreate有种工作模式,如果忘记了就回头去看看把。 createThreadProcessTemp是threadCreate工作需要的参数变量threadCreate会在0或者1这两种工作模式下 用到这个临时变量该变量作用就是告诉threadCreate要创建多少个连接,下面的一组if . else 是为了将threadCreate线程运行起来 _ps是表示当前连接池状态,下面是_ps的定义,在Java版本中PoolState只是一组pub

66、lic static final int故在这里不在将源码放出。在StartServices最后我们启动了time也就是threadCheck线程。    / 连接池状态    public enum PoolState    .        UnInitialize,/ 刚刚创建的对象,表示该对象未被调用过StartSeivice方法。 

67、60;      Initialize,/ 初始化中,该状态下服务正在按照参数初始化连接池。        Run,/运行中        Stop/停止状态    PoolState定义Java版本   /* */*     * 

68、;启动连接池服务     * throws PoolNotStopException 服务已经运行或者未完全结束     */    public void StartServices() throws PoolNotStopException .        synchronized 

69、(this) .            threadCreate.createThreadMode = 0; /工作模式0            threadCreate.createThreadProcessRun = true;     

70、0;      threadCreate.createThreadProcessTemp = _MinConnection;            if (_PoolState = PoolState_UnInitialize)            

71、;    threadCreate.start();            else if (_PoolState = PoolState_Stop)                threadCerrupt();

72、0;           else                throw new PoolNotStopException(); /服务已经运行或者未完全结束           

73、60;threadCheck.StartTimer();            threadCerrupt();/开始运行              停止服务StopService        /*/ <summary>

74、        / 停止服务,线程安全        / </summary>        public void StopServices()        . StopServices(false); 

75、        /*/ <summary>        / 停止服务,线程安全        / <param name="needs">是否必须退出;如果指定为false与StartServices()功能相同,如果指定为true。将未收回的连接资源关闭,这将是危险的。认

76、为可能你的程序正在使用此资源。</param>        / </summary>        public void StopServices(bool needs)        .        

77、0;   lock (this)            .                if (_ps = PoolState.Run)         &#

78、160;      .                    lock (hs_UseConn)                   

79、60;.                        if (needs = true)/必须退出                   &

80、#160;        hs_UseConn.Clear();                        else             &#

81、160;              if (hs_UseConn.Count != 0)                            

82、60;   throw new ResCallBackException();/连接池资源未全部回收                                     

83、60;  time.Stop();                    while (isThreadCheckRun) . /等待timer事件结束                

84、60;   createThreadProcessRun = false;                    while (threadCreate.ThreadState != ThreadState.WaitSleepJoin) . /等待可能存在的创建线程结束  

85、60;                 lock (al_All)                    .         &#

86、160;              for (int i = 0; i < al_All.Count; i+)                      

87、      (ConnStruct)al_Alli).Dispose();                        al_All.Clear();            &#

88、160;                           _ps = PoolState.Stop;                 &

89、#160;              else                    throw new PoolNotRunException();/服务未启动      

90、60;                 UpdateAttribute();/更新属性        在这里我们使用了2层锁第一层锁我们是为了保证同一时间只能有一个线程调用这个方法,而lock (hs_UseConn)则是为了保护hs_UseConn的唯一访问hs_UseConn存放的就是申请连接时注册信息,needs是将未收回的连接资源

91、也关闭,这将是危险的。认为可能你的程序正在使用此资源。if (hs_UseConn.Count != 0)                                throw new ResCallBackException

92、();/连接池资源未全部回收。这段代码是表示如果用户试图在连接没有全部释放回来时候将会引发异常,同时执行该方法的必要条件是连接池必须处在PoolState_Run状态。time.Stop();是停止检测线程的运行,while (isThreadCheckRun) .  那为什么要使用这个空循环等待timer的结束呢?原因是Timer类的运行基理,在C#下Timer触发的事件是不同于的,在.Net里无论 Timer事件处理过程的执行时间是否超过它触发时间间隔在Timer里总会在指定时间被调用,也就是说如果触发间隔却是100毫秒,然而我们的处理过程 用了500毫秒来运

93、行代码。这样的话下一个事件的触发将在我们这个事件还没有结束时又进行了,如此一来起不是灾难的!对于接下来我们还要等待 可能存在的threadCreate线程结束,不过在等待它结束时先给他发送一个暂停信号,这个信号由createThreadProcessRun 变 量传递进去。也许有人回问为什么不使用join来阻止threadCreate的运行,原因是这样的,假如threadCreate打算创建 minConnection个连接,然而恰恰在创建到minConnection-n个时候我停止也连接池,如果在这里使用join的话我们将不确 定下次恢复运行时候究竟要创建多少个连接,最好的解决办法

94、就是叫线程自己找一个安全的地方把自己join。在下面的代码就是把每一个连接分别 销毁掉并且在连接池中将它删除掉。有人说,那你只是删除了你内部的引用,的确我们只删除了内部的引用,因为销毁只是形式的销毁在.net上我们不能控制内 存去销毁一个对象,只能叫GC帮忙来清理它。在程序段的最后我们使用私有的UpdateAttribute方法来更新属性字段。 下面是Java版本的代码    /* */*     * 停止服务,线程安全    

95、0;* throws ResCallBackException 资源未全部回首     * throws PoolNotRunException 服务没有运行     */    public void StopServices() throws ResCallBackException, PoolNotRunException .

96、60;       StopServices(false);        /* */*     * 停止服务,线程安全     * param needs boolean 是否必须退出;如果指定为false与StartServices()功能相同,如果指定为true。将未收回的连接资源关

97、闭,这将是危险的。认为可能你的程序正在使用此资源。     * throws ResCallBackException 服务未启动     * throws PoolNotRunException 服务没有运行     */    public void StopServices(boolean needs) 

98、;throws PoolNotRunException, ResCallBackException .        synchronized (this) .            if (_PoolState = PoolState_Run) .     

99、           synchronized (hs_UseConn) .                    if (needs = true) /必须退出     

100、0;                  hs_UseConn.clear();                    else        

101、;            if (hs_UseConn.size() != 0)                        throw new ResCallBackException(

102、); /连接池资源未全部回收                                threadCheck.StopTimer();           

103、;     while (threadCreate.getState()!=Thread.State.WAITING) . /等待threadCreate事件结束                threadCreate.createThreadProcessRun = false;     

104、;           while (threadCreate.getState() != Thread.State.WAITING) . /等待可能存在的创建线程结束                synchronized (al_All) . &

105、#160;                  for (int i = 0; i < al_All.size(); i+)                 

106、0;      (ConnStruct) al_All.get(i).Dispose();                    al_All.clear();              &

107、#160;                 _PoolState = PoolState_Stop;             else            &

108、#160;   throw new PoolNotRunException(); /服务未启动                UpdateAttribute(); /更新属性     申请 GetConnectionFormPool        /*/ <summary>        / 在连接池中申请一个连接,使用None级别,线程安全        / </summary>        / <param name="gui">发起者</pa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论