- 浏览: 21395 次
- 性别:
- 来自: 北京
最新评论
转自:http://gaojiewyh.iteye.com/blog/411889
单例模式,它用以确保一个特定的类只有一个对象被实例化。它包含两种类型,有些书上叫singleton模式和Double—Checked Locking模式。
单例模式注意问题:
1、拥有一个特定的方法,这个方法被用于实例化需要的对象。当该方法被调用的时候,它检查这个对象是否被实例化。如果已实例化,这个方法仅仅返回这个对象的一个引用。如果对象未被实例化,这个方法将对象实例化并返回这个新的实例的引用。
2、类的构造函数定义为protected或private。
单例模式的格式
(1)懒汉式
- public class Singleton{
- //声明一个静态类的变量指向null
- private static Singleton instance = null;
- //将构造函数设为private private Singleton();
- //设计静态方法,返回类的实例
- public static Singleton getInstance(){
- if(instance==null){
- instance = new Singleton();
- return instance;
- }
- }
- }
(2)饿汉式
饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变 。
懒汉式优点是延时加载、 是在需要的时候才创建对象。缺点是应该用同步。如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。
- public class Singleton{
- private static Singleton singleton = new Singleton();
- private Singleton (){ }
- public Singleton getInstance(){
- return singletion;
- }
- }
典型应用:
数据库连接池管理类的应用
1、数据库连接池管理类
- 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();
- }
- }
- }
2、测试类
- /*
- *
- * 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);
- }
- }
3、测试结果
conn1 == com.mysql.jdbc.Connection@1f5d386
conn2 == com.mysql.jdbc.Connection@121f1d
conn3 == com.mysql.jdbc.Connection@1b8e059
conn4 == com.mysql.jdbc.Connection@910040
conn5 == com.mysql.jdbc.Connection@1a786c3
conn6 == com.mysql.jdbc.Connection@1f5d386
conn7 == com.mysql.jdbc.Connection@121f1d
conn8 == com.mysql.jdbc.Connection@1b8e059
conn9 == com.mysql.jdbc.Connection@910040
conn10 == com.mysql.jdbc.Connection@1a786c3
启动五个线程,释放后再启动仍然是原先的五个线程。
4、实际应用中的配置
上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。
Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet的 destroy方法。
根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如:
public void init() throws ServletException { connMgr = DBConnectionManager.getInstance(); } |
然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destroy方法中释放占用的系统资源,如:
public void destroy() { connMgr.release(); super.destroy(); } |
- Databasepool.rar (432.4 KB)
- 下载次数: 2
发表评论
-
最快遍历List
2012-06-27 10:55 1440最快的方法从list中取指定的值 List& ... -
java的静态与动态代理
2012-06-27 09:13 1076采用Java代理模式,代理类通过调用委托类对象的方法,来提供特 ... -
转java IO总结
2012-02-11 13:44 0java中的IO整理 写在前 ... -
Java中普通方法与静态方法static区别
2012-02-11 13:03 1110Java中普通方法与静态方法static区别 静态方法可以直 ... -
java 注解(转)
2012-02-06 12:57 900其实说起注解语法,对于任何一个Java开发人员来说都已经耳熟能 ...
相关推荐
Tongweb5是一款基于Java的Web应用服务器,它支持配置JDBC连接池来管理数据库连接。本文将详细介绍如何在Tongweb5中配置JDBC连接池,以及Web应用如何通过JNDI(Java Naming and Directory Interface)查找并使用这些...
在IT行业中,数据库连接管理是应用系统性能优化的关键环节之一,而JDBC连接池就是解决这一问题的有效工具。本文将详细讲解JDBC连接池的工作原理、配置方法以及如何通过优化来提升连接速度。 JDBC(Java Database ...
在Java开发中,数据库操作是不可或缺的一部分,而JDBC连接池是提高数据库访问效率、优化系统资源使用的重要技术。本文将深入探讨JDBC连接池的概念、工作原理,并以"通用basedao"模板为例,讲解如何在实际项目中应用...
本实例提供了完美的Java JDBC连接池配置,适用于Oracle、MySQL和SQL Server等主流数据库,允许开发者轻松地在不同数据库之间切换方言。 首先,让我们了解什么是JDBC连接池。JDBC(Java Database Connectivity)是...
JDBC(Java Database Connectivity)是Java平台中用于与数据库交互的一组接口和类,而JDBC连接池就是在这个基础上实现的一种优化策略。本文将详细介绍JDBC连接池驱动的相关知识,主要涉及`mysql-connector-java-...
本示例中的"简单的jdbc连接池类"实现了一个基本的数据库连接池功能,非常适合初学者理解和实践。 首先,我们来理解`jdbc`。JDBC(Java Database Connectivity)是Java语言用来与各种数据库进行交互的一种标准接口。...
HikariCP是一款高效、高性能的Java JDBC连接池,它被设计为替代传统连接池如C3P0和DBCP,以提供更快、更稳定的数据访问性能。在HikariCP v3.4.5这个版本中,我们可以深入探讨其在数据库连接管理、性能优化以及配置...
描述中提到的"jdbc连接池设计",意味着这个压缩包可能包含了一个简单的JDBC连接池实现或者相关的示例代码。其中,`jdom.jar`是一个Java文档对象模型库,主要用于解析XML文档。在数据库连接池的场景中,`jdom.jar`...
Java JDBC连接池是一种高效管理数据库连接的技术,它允许应用程序重复使用已经建立的数据库连接,从而减少频繁创建和关闭连接带来的开销。在大型系统中,尤其是高并发环境下,使用连接池能够显著提升性能并降低资源...
而JDBC连接池是一种管理资源的技术,它能有效地管理和复用数据库连接,提高系统性能并减少系统资源的消耗。在Java应用中,常见的连接池实现有DBCP、C3P0、HikariCP、Druid等。 标题"完美的java jdbc连接池实例.zip...
**JDBC连接池BoneCP_Demo详解** 在Java开发中,数据库操作是不可或缺的一部分,而JDBC(Java Database Connectivity)是Java与数据库交互的标准接口。然而,直接使用JDBC进行数据库连接管理可能会导致资源浪费,...
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0的主要特点包括: 1. **连接测试**:C3P0提供了多种测试策略,确保获取到的连接是可用的。 2. **连接池初始化和最大...
JDBC连接池是一种资源管理机制,它允许应用程序重复使用已建立的数据库连接,而不是每次需要时都创建新的连接。这显著提高了性能,减少了系统资源的消耗,并有助于避免由于过多的数据库连接导致的问题。在Tomcat早期...
**JDBC连接池DBCP详解** Java数据库连接池(JDBC Connection Pool)是Java应用程序管理数据库连接的一种机制,它能够有效地提高数据库访问效率并优化资源使用。DBCP(Jakarta DBCP,又称为Apache Commons DBCP)是...
关于jdbc连接池连接数据库的原理
这是我写的一个对JDBC连接池的实现,高手见了可不要笑啊!!!! 程序是在linux下用Eclipse下编写的. 用Jude进行建模,数据库使用了mysql. 程序自带了MySql的Connection连接驱动类,你也可以使用别的驱动类和数据库, 在src/...
jdbc连接池代码详解
jdbc连接池属性介绍,
"自定义高并发jdbc连接池"是一个专为处理大量并发请求而设计的解决方案,它允许应用程序高效地管理和复用数据库连接,从而减少数据库连接创建与释放的开销,提高系统的整体性能。 JDBC(Java Database Connectivity...