⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connectionpoolimpl.java

📁 OA典型例子
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.sure.dataabstraction;

import java.sql.*;
import java.util.*;
import java.io.PrintWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;

/**
 *  aggregate JDBC Connection objects implement JDBC Connections pool,it's a
 *  thread that manager all connection ,client can use getConnection to get a
 *  database connection and use free or close method to free connection (not
 *  close connection).
 *
 *@author     Mengzy
 *@date       2002-8-16
 */
public class ConnectionPoolImpl extends ConnectionPool implements Runnable {
    private Thread runner;
    //like a daemon thread to check connection
    private boolean runFlag;
    //thread run flag
    private Connection[] pool;
    //aggregate Connections
    private int[] connStatus;
    //Connection status
    private long[] connLockTime;
    //Connection locked datetime
    private long[] connCreateDate;
    //Connection create datetime in ms
    private String dbDriver;
    private String dbURL;
    private String dbUser;
    private String dbPassword;
    private int currConnCount;
    //current Connections count
    private int maxConns;
    //max Connections in this Pool
    private int initConns;
    //init Connections size in this Pool
    private int maxIdleMSec;
    //max Connections idle time in ms
    private boolean available;
    //flag this Pool is ready
    private PrintWriter log;
    //log some Exception ro error
    private SQLWarning currSQLWarning;
    //a Connection's SQLWarning
    private boolean debug;
    //output debug information
    private boolean initFlag;
    //init correctly flag

    private final static int CN_STATUS_INVALID = 0;
    //default value
    private final static int CN_STATUS_CLOSED = 1;
    //not create
    private final static int CN_STATUS_FREE = 2;
    //not used
    private final static int CN_STATUS_USED = 3;
    //used

    /**
     *  Description of the Field
     */
    public final static int MAX_USED_TIME = 1000 * 60000;


    //max connection used time 60 second

    /**
     *@param  aDatabaseInfo
     *@exception  DBPoolException  Description of the Exception
     */
    public ConnectionPoolImpl(DatabaseInfo aDatabaseInfo) throws DBPoolException {
	super(aDatabaseInfo);

	//get all database infomation for create connection pool
	dbDriver = databaseInfo.getDriverName();
	dbURL = databaseInfo.getURL();
	dbUser = databaseInfo.getUserName();
	dbPassword = databaseInfo.getPasswd();
	maxConns = databaseInfo.getPoolSize();
	initConns = databaseInfo.getInitSize();
	maxIdleMSec = (int) databaseInfo.getLifecycle() * 60000;
	//a minute in ms
	if (maxIdleMSec < 30000) {
	    maxIdleMSec = 30000;
	}

	pool = new Connection[maxConns];
	//create Connection pool array
	connCreateDate = new long[maxConns];
	//record a connection created datetime
	connLockTime = new long[maxConns];
	//record a connection locked datetime
	connStatus = new int[maxConns];
	//default value is CN_STATUS_CLOSED
	currConnCount = 0;

	try {
	    File file = new File(databaseInfo.getLogName());
	    if (!file.exists()) {
		//not exists create it
		String path = file.getPath();
		path = path.substring(0, path.lastIndexOf(file.getName()));
		//get path
		new File(path).mkdirs();
		file.createNewFile();
	    }
	    log = new PrintWriter(new FileWriter(databaseInfo.getLogName(), true), true);
	    log.println("------------------ " + new java.util.Date() + " -----------------");
	} catch (IOException e) {
	    System.err.println(e.getMessage());
	}
	//now create init Connection
	boolean flag = false;
	initFlag = false;
	if (initConns > maxConns) {
	    initConns = maxConns;
	}
	for (int i = 0; i < initConns; i++) {
	    //try to 3 times to create connection ,if failed ,throw DBException
	    for (byte retry = 1; retry <= 3; retry++) {
		try {
		    pool[i] = createConn(i);
		    flag = true;
		    currConnCount++;
		    break;
		} catch (SQLException e) {
		    log.println("Attempt (" + retry + " times of 3 of " + i + ") failed to create new database connections :");
		    log.println("-------Exception:" + e.getMessage());
		    try {
			Thread.sleep(5 * 1000);
			//try again in 5 seconds
		    } catch (InterruptedException _ie) {}
		}
		//end of try create connection
	    }
	    //end of retry 3 times
	}
	//end For of create init connection
	if (!flag) {
	    initFlag = false;
	    log.println(new java.util.Date() + "create init connection faild");
	    throw new DBPoolException("can not create connection");
	} else {
	    initFlag = true;
	}

	available = true;
	runFlag = true;
	runner = new Thread(this);
	runner.setDaemon(true);
	runner.start();
    }


    /**
     *  Description of the Method
     *
     *@param  msg  Description of the Parameter
     */
    private void debug(String msg) {
	if (debug) {
	    System.out.println(msg);
	}
    }


    /**
     *  Description of the Method
     *
     *@param  index             Description of the Parameter
     *@return                   Description of the Return Value
     *@exception  SQLException  Description of the Exception
     */
    private Connection createConn(int index) throws SQLException {
	Connection cn = null;
	if (index < 0) {
	    return null;
	}
	//create connections and put them to pool
	try {
	    java.util.Date date = new java.util.Date();
	    Class.forName(dbDriver);
	    cn = DriverManager.getConnection(dbURL, dbUser, dbPassword);
	    //get Connection
	    connCreateDate[index] = date.getTime();
	    //get create datetime stamp
	    connStatus[index] = CN_STATUS_FREE;
	    //set connection status is FALSE(not use)
	    log.println(date.toString() + " : create database connection for index " + index + " successful");
	} catch (Exception ce) {
	    throw new SQLException(ce.getMessage());
	}
	return cn;
    }


    //create next Connection return the index of connection pool
    /**
     *  Description of the Method
     *
     *@return    Description of the Return Value
     */
    private int createNextConn() {
	Connection cn = null;

	if (currConnCount > maxConns) {
	    return -1;
	}
	try {
	    //daemon thread close connection ,so we can reuse it
	    for (int i = 0; i < currConnCount; i++) {
		if ((connStatus[i] == CN_STATUS_CLOSED) || (connStatus[i] == CN_STATUS_INVALID)) {
		    debug("create next of " + i);
		    cn = createConn(i);
		    pool[i] = cn;
		    return i;
		}
	    }
	    //no closed or invalid connection must create a next conntcion
	    cn = createConn(currConnCount);
	    pool[currConnCount] = cn;
	    currConnCount++;
	    return currConnCount - 1;
	} catch (SQLException e) {
	    log.println("can not create connection Exception:" + e.getMessage());
	    return -1;
	}
    }


    /**
     *  Sets the debug attribute of the MWConnectionPoolImpl object
     *
     *@param  de  The new debug value
     */
    public void setDebug(boolean de) {
	debug = de;
    }


    /**
     */
    public void  run() {
        //System.out.println("Thread is Run");
	while (runFlag) {
	    for (int i = 0; i < currConnCount; i++) {
		//check closed
		if ((connStatus[i] == CN_STATUS_CLOSED) || (connStatus[i] == CN_STATUS_INVALID)) {
		    continue;
		}
		// if closed next connection

		//check null
		if (pool[i] == null) {
		    try {
			synchronized (this) {
			    debug("null create");
			    pool[i] = createConn(i);
			}
		    } catch (SQLException e1) {}
		    continue;
		    //next connection
		}

		//clear SQLWarning
		try {
		    currSQLWarning = pool[i].getWarnings();
		    if (currSQLWarning != null) {
			log.println("SQLWarnings ( " + i + " ) : " + currSQLWarning);
			pool[i].clearWarnings();
		    }
		} catch (SQLException e2) {}

		//check connection open status
		try {
		    if ((connStatus[i] == CN_STATUS_FREE) && (pool[i].isClosed())) {
			//connection close ,so recreate it
			synchronized (this) {
			    debug("close create");
			    log.println(new java.util.Date() + " : connection of " + i + " was recreated");
			    pool[i] = createConn(i);
			}
		    }
		} catch (SQLException e3) {}

		//check use time
		try {
		    if ((connStatus[i] == CN_STATUS_USED) &&
			    (System.currentTimeMillis() - connLockTime[i] > MAX_USED_TIME)) {
			debug("use time create");
			pool[i].close();
			synchronized (this) {
			    pool[i] = createConn(i);
			}
		    }
		} catch (SQLException e4) {}

		//check connection idle time
		try {
		    if ((connStatus[i] == CN_STATUS_FREE) &&
			    (getAvailableCount() > initConns) &&
			    ((System.currentTimeMillis() - connLockTime[i]) > maxIdleMSec)) {
			//close connection and set null
			synchronized (connStatus) {
			    pool[i].close();
			    pool[i] = null;
			    connStatus[i] = CN_STATUS_CLOSED;
			    log.println("Recycle connection ( " + i + " )");
			}
		    }
		} catch (SQLException e5) {}
	    }
	    // end of for
	    try {
		Thread.sleep(500);
	    }
	    //sleep 500 ms
	    catch (InterruptedException ee) {}
	}
	// end of while
    }


    /**
     *@return                      Connection
     *@exception  DBPoolException
     *@roseuid                     3BF1CE1E0268
     */
    public Connection getConnection() throws DBPoolException {
	if (!initFlag) {
	    throw new DBPoolException("Connection pool do not init correctly, please check Connection Pool error log");
	}
	Connection cn = null;
	boolean flag = false;
	if (!available) {
	    throw new DBPoolException("can not getConnection while destory()");
	}

	//check opened connection
	synchronized (connStatus) {
	    if (getUsedCount() < getAvailableCount()) {
		for (int i = 0; i < currConnCount; i++) {
		    if (connStatus[i] == CN_STATUS_FREE) {
			cn = pool[i];
			debug("get connection of " + i);
			try {
			    if (cn.isClosed()) {
				//this Connection was closed ,so must create a new instance
				debug("UsedCount < AvailableCount Close : Create");
				pool[i] = createConn(i);
				cn = pool[i];
			    }
			} catch (SQLException e) {
			    System.out.println("getConnectino Exception:" + e.getMessage());
			}
			//get connection so must set flag
			connStatus[i] = CN_STATUS_USED;
			connLockTime[i] = System.currentTimeMillis();
			flag = true;
			break;
			//now get it ( a Connection so break )
		    }
		}
	    }
	}
	//end of synchronized (connStatus)
	if (flag) {
	    return new ConnectionWrapper(cn, this);
	}

	//no free connection
	if (getAvailableCount() < maxConns) {
	    // all exists connection was used so must create new connection (not exceed maxConn)
	    synchronized (this) {
		System.out.println("Create next connection");
		int index = createNextConn();
		if (index != -1) {
		    cn = pool[index];
		    connStatus[index] = CN_STATUS_USED;
		    connLockTime[index] = System.currentTimeMillis();
		    flag = true;
		} else {
		    //create faild set flag = close
		    connStatus[index] = CN_STATUS_CLOSED;
		}
	    }
	    //end of synchronized(this)
	} else {
	    //currConnCount >= maxConns

	    //because all connection was used ,so must wait client free connection
	    int retry = 0;
	    while (getUsedCount() >= getAvailableCount()) {
		//just wait 200 ms
		try {
		    Thread.sleep(200);
		    retry++;
		} catch (InterruptedException _ex) {}
		if (retry >= 50) {
		    //10 seconds
		    throw new DBPoolException("all connection is busy, please try again");
		}
	    }
	    //end of while
	    //now one connection was freed ,so can get it from pool
	    //lock connStatus
	    synchronized (connStatus) {
		for (int i = 0; i < currConnCount; i++) {
		    if (connStatus[i] == CN_STATUS_FREE) {
			cn = pool[i];
			try {
			    if (cn.isClosed()) {
				//this Connection was closed ,so must create a new instance
				pool[i] = createConn(i);
				cn = pool[i];
			    }
			} catch (SQLException e) {}
			connLockTime[i] = System.currentTimeMillis();
			connStatus[i] = CN_STATUS_USED;
			flag = true;
			break;
			//get a connection so break
		    }
		}
		//end of for
	    }
	    //end of synchronized (connStatus)
	}
	//end of else currConnCount >= maxConns
	if (flag) {
	    return new ConnectionWrapper(cn, this);
	}
	throw new DBPoolException("can not get a connection ,please check your database's status");
    }


    /**
     */
    public void destroy() {
	available = false;
	runFlag = false;
	runner.interrupt();
	try {
	    runner.join(1000 * 10);
	    //wait 10 seconds thread will die
	} catch (InterruptedException _ex) {}
	//just wait all connection pull back to pool
	for (long l = System.currentTimeMillis();
		(getUsedCount() > 0) && (System.currentTimeMillis() - l <= 1000 * 10); ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -