單例模式的優勢

轉載:http://blog.csdn.net/cnjavatyro/article/details/6225817java

單例模式是一種常見的設計模式,在《Java與模式》一書中,閻宏博士對單例模式作了全面的總結。mysql

 

Java Singleton模式就爲咱們提供了這樣實現的可能。使用Singleton的好處還在於能夠節省內存,由於它限制了實例的個數,sql

有利於Java垃圾回收(garbage collection)。數據庫

 

 

 單例模式也是一種比較常見的設計模式,它到底能帶給咱們什麼好處呢?其實無非是三個方面的做用:編程

     一、控制資源的使用,經過線程同步來控制資源的併發訪問;設計模式

     二、控制實例產生的數量,達到節約資源的目的。多線程

     三、做爲通訊媒介使用,也就是數據共享,它能夠在不創建直接關聯的條件下,讓多個不相關的兩個線程或者進程之間實現通訊。併發

 

 

單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。框架

單例模式有一下特色:函數

一、單例類只能有一個實例。

二、單例類必須本身建立本身的惟一實例。

三、單例類必須給全部其餘對象提供這一實例。

說明:一下的代碼來自閻宏博士的《Java與模式》一書,其中對一些類的寫法作調整(符合Java1.5的習慣),另外還加了測試方法。

1、懶漢式單例

在類被加載的時候,惟一實例已經被建立。這個設計模式在Java中容易實現,在別的語言中難以實現。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 14:57:08

* <> 單例模式-懶漢式單例

*/

public class LazySingleton {

     /**

      * 私有靜態對象,加載時候不作初始化

      */

     private static LazySingleton m_intance=null;

     /**

      * 私有構造方法,避免外部建立實例

      */

     private LazySingleton(){

     }

     /**

      * 靜態工廠方法,返回此類的惟一實例. 

      * 當發現實例沒有初始化的時候,才初始化.

      * @return LazySingleton

      */

     synchronized public static LazySingleton getInstance(){

         if(m_intance==null){

             m_intance=new LazySingleton();

         }

         return m_intance;

     }

}

2、餓漢式單例

在類加載的時候不建立單例實例。只有在第一次請求實例的時候的時候建立,而且只在第一次建立後,之後再也不建立該類的實例。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 14:45:25

* <> 單例模式-餓漢式單例

*/

public class EagerSingleton {

     /**

      * 私有的(private)惟一(static final)實例成員,在類加載的時候就建立好了單例對象

      */

     private static final EagerSingleton m_instance = new EagerSingleton();

     /**

      * 私有構造方法,避免外部建立實例

      */

     private EagerSingleton() {

     }

     /**

      * 靜態工廠方法,返回此類的惟一實例.

      * @return EagerSingleton

      */

     public static EagerSingleton getInstance() {

         return m_instance;

     }

}

3、登記式單例

這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,然後返回。

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 15:20:16

* <> 單例模式- 登記式單例

*/

public class RegSingleton {

     /**

      * 登記薄,用來存放全部登記的實例

      */

     private static Map m_registry = new HashMap();

     //在類加載的時候添加一個實例到登記薄

     static {

         RegSingleton x = new RegSingleton();

         m_registry.put(x.getClass().getName(), x);

     }

     /**

      * 受保護的默認構造方法

      */

     protected RegSingleton() {

     }

     /**

      * 靜態工廠方法,返回指定登記對象的惟一實例;

      * 對於已登記的直接取出返回,對於還未登記的,先登記,而後取出返回

      * @param name

      * @return RegSingleton

      */

     public static RegSingleton getInstance(String name) {

         if (name == null) {

             name = "RegSingleton";

         }

         if (m_registry.get(name) == null) {

             try {

                 m_registry.put(name, (RegSingleton) Class.forName(name).newInstance());

             } catch (InstantiationException e) {

                 e.printStackTrace();

             } catch (IllegalAccessException e) {

                 e.printStackTrace();

             } catch (ClassNotFoundException e) {

                 e.printStackTrace();

             }

         }

         return m_registry.get(name);

     }

     /**

      * 一個示意性的商業方法

      * @return String

      */

     public String about() {

         return "Hello,I am RegSingleton!";

     }

}

4、單例模式的一個應用

該應用是配置文件管理類。爲了本例能正確運行,我在C盤下先創建了一個xxxx.properties文件,內容以下:

-------------------

user=root

password=leizhimin

這個配置文件管理類的代碼以下:

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 15:55:01

* 單例模式應用-單例類應用-配置文件管理

*/

public class ConfigManager {

     /**

      * 屬性文件全名

      */

     private static final String PFILE = "C:/xxx.properties";

     /**

      * 對應於屬性文件的文件對象變量

      */

     private File m_file = null;

     /**

      * 屬性文件的最後修改日期

      */

     private long m_lastModifiedTime = 0;

     /**

      * 屬性文件所對應的屬性對象變量

      */

     private Properties m_props = null;

     /**

      * 本類可能存在的惟一的一個實例

      */

     private static ConfigManager m_instance = new ConfigManager();

     /**

      * 私有構造子,用以保證外界沒法直接實例化

      */

     private ConfigManager() {

         m_file = new File(PFILE);

         m_lastModifiedTime = m_file.lastModified();

         if (m_lastModifiedTime == 0) {

             System.err.println(PFILE + " file does not exist!");

         }

         m_props = new Properties();

         try {

             m_props.load(new FileInputStream(PFILE));

         } catch (IOException e) {

             e.printStackTrace();

         }

     }

     /**

      * 靜態工廠方法

      *

      * @return ConfigManager

      */

     synchronized public static ConfigManager getInstance() {

         return m_instance;

     }

     /**

      * 獲取屬性配置項的值

      *

      * @param name

      * @param defaultVal

      * @return Object

      */

     public final Object getConfigItem(String name, Object defaultVal) {

         long newTime = m_file.lastModified();

         if (newTime == 0) {

             //屬性文件不存在

             if (m_lastModifiedTime == 0) {

                 System.err.println(PFILE + " file does not exist!");

             } else {

                 System.err.println(PFILE + " file was deleted!");

             }

             return defaultVal;

         } else if (newTime > m_lastModifiedTime) {

             m_props.clear();

             try {

                 m_props.load(new FileInputStream(PFILE));

             } catch (IOException e) {

                 e.printStackTrace();

             }

         }

         m_lastModifiedTime = newTime;

         Object val = m_props.getProperty(name);

         if (val == null) {

             return defaultVal;

         } else {

             return val;

         }

     }

}

測試配置文件類:

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2007-9-11

* Time: 16:42:45

* 配置文件管理類測試

*/

public class Test_ConfigManager {

     public static void main(String[] args) {

         ConfigManager cfgm = ConfigManager.getInstance();

         Object val1 = cfgm.getConfigItem("sdf", "leizhimin");

         Object val2 = cfgm.getConfigItem("user", "leizhimin");

         System.out.println(val1.toString());

         System.out.println(val2.toString());

     }

}

運行結果:

leizhimin

root

Process finished with exit code 0

5、筆者寫的一個JDBC數據庫工具類的單例實現

/**

* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2005-9-11

* Time: 18:04:46

* 單例模式在JDBC編程中的應用,用於設計數據庫工具類

*/

public class DBUtil {

     //單一實例

     private static final DBUtil _instance = new DBUtil();

     //數據源的JNDI

     private static final String datasource = "java:comp/env/jdbc/zvfims";

     /**

      * 私有構造方法,防止外部實例化

      */

     private DBUtil() {

     }

     /**

      * 數據庫工具類實例工廠

      *

      * @return DBUtil

      */

     public DBUtil getInstance() {

         return _instance;

     }

     /**

      * 業務方法:用於獲取數據庫鏈接

      *

      * @return Connection

      */

     public Connection makeConnection() {

         Connection conn = null;

         try {

             Context ctx = new InitialContext();

             DataSource ds = (DataSource) ctx.lookup(datasource);

             conn = ds.getConnection();

         } catch (NamingException e) {

             System.out.println("獲取數據源異常,請AppServer的JNDI數據源配置!");

             e.printStackTrace();

         } catch (SQLException e) {

             System.err.println("獲取數據庫鏈接發生異常!");

             e.printStackTrace();

         }

         return conn;

     }

}

經過這個單例類和開放的業務方法,能夠爲整個系統應用提供數據庫鏈接。 

 

 

********************************************************************************************

 

單例模式的實現方式:懶漢單例類和餓漢單例類 

單例模式的實現有多種方法,常見的就有懶漢式單例類和餓漢式單例類。咱們前面介紹的實現方法就屬於懶漢式單例類。 

懶漢式單例類 

對於懶漢模式,咱們能夠這樣理解:該單例類很是懶,只有在自身須要的時候纔會行動,歷來不知道及早作好準備。它在須要對象的時候,才判斷是否已有對象,若是沒有就當即建立一個對象,而後返回,若是已有對象就再也不建立,當即返回。 

懶漢模式只在外部對象第一次請求實例的時候纔去建立。 

餓漢式單例 

對於餓漢模式,咱們能夠這樣理解:該單例類很是餓,迫切須要吃東西,因此它在類加載的時候就當即建立對象。 

咱們對比一下懶漢模式和餓漢模式的優缺點: 

懶漢模式,它的特色是運行時得到對象的速度比較慢,但加載類的時候比較快。它在整個應用的生命週期只有一部分時間在佔用資源。 

餓漢模式,它的特色是加載類的時候比較慢,但運行時得到對象的速度比較快。它從加載到應用結束會一直佔用資源。 

這 兩種模式對於初始化較快,佔用資源少的輕量級對象來講,沒有多大的性能差別,選擇懶漢式仍是餓漢式都沒有問題。可是對於初始化慢,佔用資源多的重量級對象 來講,就會有比較明顯的差異了。因此,對重量級對象應用餓漢模式,類加載時速度慢,但運行時速度快;懶漢模式則與之相反,類加載時速度快,但運行時第一次 得到對象的速度慢。 

從用戶體驗的角度來講,咱們應該首選餓漢模式。咱們願意等待某個程序花較長的時間初始化,卻不喜歡在程序運行時等待過久,給人一種反應遲鈍的感受,因此對於有重量級對象參與的單例模式, 咱們推薦使用餓漢模式 。 

而 對於初始化較快的輕量級對象來講,選用哪一種方法均可以。若是一個應用中使用了大量單例模式,咱們就應該權衡兩種方法了。輕量級對象的單例採用懶漢模式,減 輕加載時的負擔,縮短加載時間,提升加載效率;同時因爲是輕量級對象,把這些對象的建立放在使用時進行,實際就是把建立單例對象所消耗的時間分攤到整個應 用中去了,對於整個應用的運行效率沒有太大影響。 

 

什麼狀況下使用單例模式 

單例模式也是一種比較常見的設計模式,它到底能帶給咱們什麼好處呢?其實無非是三個方面的做用: 

第1、控制資源的使用,經過線程同步來控制資源的併發訪問; 

第2、控制實例產生的數量,達到節約資源的目的。 

第3、做爲通訊媒介使用,也就是數據共享,它能夠在不創建直接關聯的條件下,讓多個不相關的兩個線程或者進程之間實現通訊。 

好比,數據庫鏈接池的設計通常採用單例模式,數據庫鏈接是一種數據庫資源。軟件系統中使用數據庫鏈接池,主要是節省打開或者關閉數據庫鏈接所引發的效率損 耗,這種效率上的損耗仍是很是昂貴的。固然,使用數據庫鏈接池還有不少其它的好處,能夠屏蔽不一樣數據數據庫之間的差別,實現系統對數據庫的低度耦合,也可 以被多個系統同時使用,具備高可複用性,還能方便對數據庫鏈接的管理等等。數據庫鏈接池屬於重量級資源,一個應用中只須要保留一份便可,既節省了資源又方 便管理。因此數據庫鏈接池採用單例模式進行設計會是一個很是好的選擇。 

 

在咱們平常使用的在Windows中也有很多單例模式設計的組件,象 經常使用的文件管理器。因爲Windows操做系統是一個典型的多進程多線程系統,那麼在建立或者刪除某個文件的時候,就不可避免地出現多個進程或線程同時操 做一個文件的現象。採用單例模式設計的文件管理器就能夠完美的解決這個問題,全部的文件操做都必須經過惟一的實例進行,這樣就不會產生混亂的現象。 

再 好比,每臺計算機能夠有若干個打印機,若是每個進程或者線程都獨立地使用打印機資源的話,那麼咱們打印出來的結果就有可能既包含這個打印任務的一部分, 又包含另一個打印任務的一部分。因此,大多數的操做系統最終爲打印任務設計了一個單例模式的假脫機服務Printer Spooler,全部的打印任務都須要經過假脫機服務進行。 

實際上,配置信息類、管理類、控制類、門面類、代理類一般被設計爲單例類。像Java的Struts、Spring框架,.Net的Spring.Net框架,以及Php的Zend框架都大量使用了單例模式。 

回答人的補充   2010-04-13 13:22 

使用單例模式最核心的一點是體現了面向對象封裝特性中的「單一職責」和「對象自治」原則。 

不少時候咱們要保證類的實例只有一個。咱們可能在本身的代碼中判斷須要的類的實例有無,無就new一個。這樣看似不錯。問題是,你用到這個類的地方有n個,這樣你就須要n個判斷。爲何不把這個職責交給類自己呢?而後讓類提供一個接口訪問。

 

 

 

******************************************************************************************

 

所謂「懶漢式」與「餓漢式」的區別,是在與創建單例對象的時間不一樣。
「懶漢式」是在你真正用到的時候纔去建這個單例對象:
好比:有個單例對象
     private static Student student = null;  //不創建對象
     Student getInstance(){
             if(student == null) {        //先判斷是否爲空
                student = new Student();  //懶漢式作法 
             }
             return student;
          }

「餓漢式」是在無論你用的用不上,一開始就創建這個單例對象:
好比:有個單例對象
      private static Student student = new Student(); //創建對象
      Student getInstance(){
                return student;  //直接返回單例對象
          }

 

 

******************************************************************************************

 

單例模式----數據庫鏈接池管理類的應用

 

package com.cvicse.util;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.sql.Connection;

import java.sql.Driver;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.util.Date;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.Properties;

import java.util.StringTokenizer;

import java.util.Vector;

 

/**

 * 數據庫鏈接池管理類

 * 

 * @功能 :管理類DBConnectionManager支持對一個或多個由屬性文件定義的數據庫鏈接池的訪問.

 *     客戶程序能夠調用getInstance()方法訪問本類的惟一實例

 * @建立人 gao_jie

 * @建立日期 Jun 18, 2009

 * @版本 1.0

 * 

 */

public class DBConnectionManager {

 

private static DBConnectionManager instance; // 惟一實例

private static int clients; // 鏈接的客戶端

private Vector drivers = new Vector();// 驅動集合

private Hashtable pools = new Hashtable();// 鏈接池

private Properties dbProps;// 屬性文件

private PrintWriter log; // 日誌變量

 

/**

* 單例模式建構私有函數以防止其它對象建立本類實例

*/

private DBConnectionManager() {

this.init();

}

 

/**

* 採用單例模式,返回惟一實例.若是是第一次調用此方法,則建立實例

* @return DBConnectionManager 惟一實例

*/

public static synchronized DBConnectionManager getInstance() {

if (instance == null) {

instance = new DBConnectionManager();

}

clients++;

return instance;

}

 

/**

* 得到一個可用的(空閒的)鏈接.若是沒有可用鏈接,且已有鏈接數小於最大鏈接數 限制,則建立並返回新鏈接

* @param name

*            在屬性文件中定義的鏈接池名字

* @return Connection 可用鏈接或null

*/

public Connection getConnection(String name) {

DBConnectionPool dbPool = (DBConnectionPool) pools.get(name);

if (dbPool != null) {

return dbPool.getConnection();

}

return null;

}

 

/**

* 得到一個可用鏈接.若沒有可用鏈接,且已有鏈接數小於最大鏈接數限制, 則建立並返回新鏈接. 不然,在指定的時間內等待其它線程釋放鏈接.

* @param name

*            鏈接池名字

* @param time

*            以毫秒計的等待時間

* @return Connection 可用鏈接或null

*/

public Connection getConnection(String name, long time) {

DBConnectionPool dbPool = (DBConnectionPool) pools.get(name);

if (dbPool != null) {

return dbPool.getConnection(time);

}

return null;

}

 

/**

* 將鏈接對象返回給由名字指定的鏈接池

* @param name

*            在屬性文件中定義的鏈接池名字

* @param con

*            鏈接對象

*/

public void freeConnection(String name, Connection con) {

DBConnectionPool dbPool = (DBConnectionPool) pools.get(name);

if (dbPool != null) {

dbPool.freeConnection(con);

}

}

 

/**

* 關閉全部鏈接,撤銷驅動程序的註冊

*/

public synchronized void release() {

// 等待直到最後一個客戶程序調用

if (--clients != 0) {

return;

}

Enumeration allPools = pools.elements();

while (allPools.hasMoreElements()) {

DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();

pool.release();

}

Enumeration allDrivers = drivers.elements();

while (allDrivers.hasMoreElements()) {

Driver driver = (Driver) allDrivers.nextElement();

try {

DriverManager.deregisterDriver(driver);

log("撤銷JDBC驅動程序 " + driver.getClass().getName() + "的註冊");

} catch (SQLException e) {

log(e, "沒法撤銷下列JDBC驅動程序的註冊: " + driver.getClass().getName());

}

}

}

 

/**

* 讀取屬性完成初始化

*/

private void init() {

 

// 文件流輸入方式

InputStream fileinputstream = null;

try {

fileinputstream = new FileInputStream("./src/db.properties");

} catch (FileNotFoundException e) {

e.printStackTrace();

}

try {

dbProps = new Properties();

dbProps.load(fileinputstream);

} catch (Exception e) {

e.printStackTrace();

System.err.println("不能讀取屬性文件. "

+ "請確保db.properties在CLASSPATH指定的路徑中");

return;

}

 

String logFile = dbProps.getProperty("logfile",

"DBConnectionManager.log");

try {

log = new PrintWriter(new FileWriter(logFile, true), true);

} catch (IOException e) {

System.err.println("沒法打開日誌文件: " + logFile);

log = new PrintWriter(System.err);

}

// 加載驅動

loadDrivers(dbProps);

// 建立鏈接池

createPools(dbProps);

}

 

/**

* 裝載和註冊全部JDBC驅動程序

* @param props

*            屬性

*/

private void loadDrivers(Properties props) {

String driverClasses = props.getProperty("drivers");

StringTokenizer st = new StringTokenizer(driverClasses);

while (st.hasMoreElements()) {

String driverClassName = st.nextToken().trim();

try {

Driver driver = (Driver) Class.forName(driverClassName)

.newInstance();

DriverManager.registerDriver(driver);

drivers.addElement(driver);

log("成功註冊JDBC驅動程序" + driverClassName);

} catch (Exception e) {

log("沒法註冊JDBC驅動程序: " + driverClassName + ", 錯誤: " + e);

}

}

}

 

/**

* 根據指定屬性建立鏈接池實例.

* @param props

*            鏈接池屬性

*/

private void createPools(Properties props) {

Enumeration propNames = props.propertyNames();

while (propNames.hasMoreElements()) {

String name = (String) propNames.nextElement();

if (name.endsWith(".url")) {

String poolName = name.substring(0, name.lastIndexOf("."));

System.out.println(" poolName ||" + poolName + "|");

String url = props.getProperty(poolName + ".url");

if (url == null) {

log("沒有爲鏈接池" + poolName + "指定URL");

continue;

}

String user = props.getProperty(poolName + ".user");

String password = props.getProperty(poolName + ".password");

String maxconn = props.getProperty(poolName + ".maxconn", "0");

int max;

try {

max = Integer.valueOf(maxconn).intValue();

} catch (NumberFormatException e) {

log("錯誤的最大鏈接數限制: " + maxconn + " .鏈接池: " + poolName);

max = 0;

}

DBConnectionPool pool = new DBConnectionPool(poolName, url,

user, password, max);

pools.put(poolName, pool);

log("成功建立鏈接池" + poolName);

}

}

}

 

/**

* 將文本信息寫入日誌文件

*/

private void log(String msg) {

log.println(new Date() + ": " + msg);

}

 

/**

* 將文本信息與異常寫入日誌文件

*/

private void log(Throwable e, String msg) {

log.println(new Date() + ": " + msg);

e.printStackTrace(log);

}

 

/***************************************************************************

************************數據庫鏈接池內部類************************************

**************************************************************************/

/**

* @功能:數據庫鏈接池內類 此內部類定義了一個鏈接池.它可以根據要求建立新鏈接,直到預約的最大鏈接數爲止.

*              在返回鏈接給客戶程序以前,它可以驗證鏈接的有效性.

* @建立人 gao_jie

* @建立日期 Jun 19, 2009

* @版本 1.0

*/

class DBConnectionPool {

 

private String poolName; // 鏈接池名字

private String dbConnUrl; // 數據庫的JDBC URL

private String dbUserName; // 數據庫帳號或null

private String dbPassWord; // 數據庫帳號密碼或null

private int maxConn; // 此鏈接池容許創建的最大鏈接數

private int checkedOut; // 當前鏈接數

private Vector<Connection> freeConnections; // 保存全部可用鏈接

 

/**

* 建立新的鏈接池構造函數

* @param poolName

*            鏈接池名字

* @param dbConnUrl

*            數據庫的JDBC URL

* @param dbUserName

*            數據庫賬號或 null

* @param dbPassWord

*            密碼或 null

* @param maxConn

*            此鏈接池容許創建的最大鏈接數

*/

public DBConnectionPool(String poolName, String dbConnUrl,

String dbUserName, String dbPassWord, int maxConn) {

this.poolName = poolName;

this.dbConnUrl = dbConnUrl;

this.dbUserName = dbUserName;

this.dbPassWord = dbPassWord;

this.maxConn = maxConn;

this.freeConnections = new Vector<Connection>();

}

 

/**

* 從鏈接池得到一個可用鏈接.若是沒有空閒的鏈接且當前鏈接數小於最大鏈接 數限制,則建立新鏈接.

* 如原來登記爲可用的鏈接再也不有效,則從向量刪除之,而後遞歸調用本身以嘗試新的可用鏈接.

*/

public synchronized Connection getConnection() {

Connection conn = null;// 定義鏈接標量

if (freeConnections != null && freeConnections.size() > 0) {

// 獲取向量中第一個可用鏈接

conn = (Connection) freeConnections.firstElement();

freeConnections.removeElementAt(0);

try {

if (conn.isClosed()) {

log("從鏈接池" + poolName + "刪除一個無效鏈接");

// 遞歸調用本身,嘗試再次獲取可用鏈接

conn = getConnection();

}

} catch (SQLException e) {

log("從鏈接池" + poolName + "刪除一個無效鏈接");

// 遞歸調用本身,嘗試再次獲取可用鏈接

conn = getConnection();

}

} else if (maxConn == 0 || checkedOut < maxConn) {

conn = newConnection();

}

if (conn != null) {

checkedOut++;

}

return conn;

}

 

/**

* 從鏈接池獲取可用鏈接.能夠指定客戶程序可以等待的最長時間 參見前一個getConnection()方法.

* @param timeout

*            以毫秒計的等待時間限制

*/

public synchronized Connection getConnection(long timeout) {

long startTime = System.currentTimeMillis();

Connection conn = null;// 定義鏈接標量

while ((conn = getConnection()) == null) {

try {

wait(timeout);

} catch (InterruptedException e) {

e.printStackTrace();

}

if ((System.currentTimeMillis() - startTime) >= timeout) {

// wait()返回的緣由是超時

return null;

}

}

return conn;

}

 

/**

* 建立新的鏈接

* @return 返回數據庫鏈接

*/

private Connection newConnection() {

Connection conn = null;// 定義鏈接標量

try {

if (dbUserName == null) {

conn = DriverManager.getConnection(dbConnUrl);

} else {

conn = DriverManager.getConnection(dbConnUrl, dbUserName,

dbPassWord);

}

log("鏈接池" + poolName + "建立一個新的鏈接");

} catch (SQLException e) {

log(e, "沒法建立下列URL的鏈接: " + dbConnUrl);

return null;

}

return conn;

}

 

/**

* 將再也不使用的鏈接返回給鏈接池

* @param con

*            客戶程序釋放的鏈接

*/

public synchronized void freeConnection(Connection conn) {

// 將指定鏈接加入到向量末尾

freeConnections.addElement(conn);

checkedOut--;

notifyAll(); // 刪除等待隊列中的全部線程

}

 

/**

* 關閉全部鏈接

*/

public synchronized void release() {

Enumeration<Connection> allConnections = freeConnections.elements();

while (allConnections.hasMoreElements()) {

Connection con = (Connection) allConnections.nextElement();

try {

con.close();

log("關閉鏈接池" + poolName + "中的一個鏈接");

} catch (SQLException e) {

log(e, "沒法關閉鏈接池" + poolName + "中的鏈接");

}

}

freeConnections.removeAllElements();

}

}

}

 

 

 

測試類

 

/*

 * 

 * InforGuard Copyright 2008 CVICSE, Co.ltd . 

 * All rights reserved.

 *  

 * Package:  com.cvicse.util

 * FileName: Test.java

 * 

 */

 

package com.cvicse.util;

 

import java.sql.Connection;

 

/**

 * 

 * @功能

 * @建立人 gao_jie

 * @建立日期 Jun 19, 2009

 * @版本 1.0

 * 

 */

public class Test {

 

/**

* @param args

*/

public static void main(String[] args) {

// 文件流輸入方式

DBConnectionManager connectionManager = DBConnectionManager

.getInstance();

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Connection conn1 = connectionManager.getConnection("mysql");

Connection conn2 = connectionManager.getConnection("mysql");

Connection conn3 = connectionManager.getConnection("mysql");

Connection conn4 = connectionManager.getConnection("mysql");

Connection conn5 = connectionManager.getConnection("mysql");

System.out.println(" conn1 == " + conn1);

System.out.println(" conn2 == " + conn2);

System.out.println(" conn3 == " + conn3);

System.out.println(" conn4 == " + conn4);

System.out.println(" conn5 == " + conn5);

 

connectionManager.freeConnection("mysql", conn1);

connectionManager.freeConnection("mysql", conn2);

connectionManager.freeConnection("mysql", conn3);

connectionManager.freeConnection("mysql", conn4);

connectionManager.freeConnection("mysql", conn5);

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Connection conn6 = connectionManager.getConnection("mysql");

Connection conn7 = connectionManager.getConnection("mysql");

Connection conn8 = connectionManager.getConnection("mysql");

Connection conn9 = connectionManager.getConnection("mysql");

Connection conn10 = connectionManager.getConnection("mysql");

System.out.println(" conn6 == " + conn6);

System.out.println(" conn7 == " + conn7);

System.out.println(" conn8 == " + conn8);

System.out.println(" conn9 == " + conn9);

System.out.println(" conn10 == " + conn10);

}

}

相關文章
相關標籤/搜索