단일 모드 ---데이터베이스 연결 풀 관리 클래스의 응용

특정한 클래스가 하나의 대상만 실례화되는 것을 확보하기 위한 단일 모드Singleton 모드와 Double - Checked Locking 모드라는 두 가지 유형으로 구성됩니다.
단일 모드 참고 사항:
1. 특정한 방법을 가지고 있는데 이 방법은 실례화에 필요한 대상에 사용된다.이 방법이 호출되었을 때, 그것은 이 대상이 실례화되었는지 검사한다.만약 이미 실례화되었다면, 이 방법은 단지 이 대상의 인용만을 되돌려줄 뿐이다.만약 대상이 실례화되지 않았다면, 이 방법은 대상을 실례화하고 이 새로운 실례의 인용을 되돌려줍니다.
2. 클래스의 구조 함수는protected 또는private로 정의된다.
단일 모드 형식
(1) 게으름뱅이
public class Singleton{ 
//            null 
private static Singleton instance = null; 
//       private private Singleton(); 
//      ,       
public static synchronized 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. 실제 응용에서의 구성
위에서 실현된 연결 탱크는 프로그램 개발 시 어떻게 시스템에 응용됩니까?다음은 서브렛의 예를 들어 연결 풀의 사용을 설명합니다.서브렛의 라이프 사이클은 서브렛을 시작할 때 초기화(init) 방법을 호출하는 것입니다.이후 모든 사용자의 요청은 이전에 만들어진 실례적인 서비스 방법을 호출하는 루트를 초래합니다.마지막으로, 서버가 servlet을 마운트 해제하기로 결정했을 때, 이 servlet의destroy 방법을 먼저 호출합니다.servlet의 특징에 따라 우리는 초기화 함수에서 연결 탱크 관리 클래스의 유일한 예를 생성할 수 있다. (그 중에서 하나 이상의 연결 탱크를 만드는 것을 포함한다.)예:
public void init() throws ServletException{ connMgr = DBConnectionManager.getInstance(); }
그리고 서비스 방법에서 연결 탱크의 이름을 통해 연결 탱크를 사용하여 데이터베이스 조작을 수행할 수 있다.마지막으로destroy 방법에서 사용된 시스템 자원을 방출합니다. 예를 들어 다음과 같습니다.
public void destroy() {  connMgr.release(); super.destroy(); }
 

좋은 웹페이지 즐겨찾기