如题,网上找了很久,没找到,以前只用过JSP MYSQL的连接池,实在不想花时间去一个个试了-_-

解决方案 »

  1.   

    package com.cc.connectionpool;import java.io.IOException;
    import java.sql.*;
    import java.util.Date;
    import javax.management.StringValueExp;public class ConnectionPool implements Runnable {
    //private boolean _debug=false;
    private Thread runner; //数据库池线程
    private Connection[] connPool; //数据库池中的连接数组
    private int[] connStatus; //记录连接池中每个连接的状态。
    //当connStatus[i]=0时,代表连接可用,为1时代码被用户锁定,
        // 值为2时代表被管理员线程锁定。
    private long[] connLockTime; //记录每个连接被锁定的时间
    private long[] connCreateTime; //记录每个连接被创建的时间
    private String[] connID; //记录每个连接的标识号
    private String dbdriver,dbserver,dbuser,dbpassword;
    //dbdriver表示连接驱动,dbserver表示注册字符,dbuser表示用户,dbpassword表示用户口令
    private int currConnections,connLast,minconns,maxconns,maxconnMSec;
    private boolean available=true; //当连接池撤销时值为false,调用getConnetcion()方法时检查available
    private SQLWarning currSQLWarning;

    //定义两个构造方法,其中一个为默认参数
    public ConnectionPool(String dbdriver,String dbserver,String dbuser,String dbpassword,int minconns,int maxconns,double maxconntime){
    try {
    initConnectionPool(dbdriver,dbserver,dbuser,dbpassword,minconns,maxconns,maxconntime);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    /*
    public ConnectionPool(){
    try {
    String dbdriver="com.microsoft.sqlserver.jdbc.SQLServerDriver";
    String dbserver="jdbc:sqlserver://localhost:1433;DatabaseName=Player";
    String username="yuqing";
    String password="1234";
    initConnectionPool(dbdriver,dbserver,username,password,30,100,0.1);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    */
    public void initConnectionPool(String dbdriver,String dbserver,String dbuser,String dbpassword,int minconns,int maxconns,double maxconntime)throws IOException{
    connPool=new Connection[maxconns];
    connStatus=new int[maxconns];
    connLockTime=new long[maxconns];
    connCreateTime=new long[maxconns];
    connID=new String[maxconns];
    currConnections=minconns;
    this.dbdriver=dbdriver;
    this.dbserver=dbserver;
    this.dbuser=dbuser;
    this.dbpassword=dbpassword;
    maxconnMSec=(int)(maxconntime*3600*1000);
    //maxconntime表示的是连接重置之间的最大时间差
    if(maxconnMSec<60000){
    maxconnMSec=60000;
    }//当maxconnMSec小于一分钟,则赋值为一分钟
    init();
    runner=new Thread(this);
    runner.start();
    }

    //下面是初始化方法,功能是建立指定初始个数的连接,若某个连接创建不成功,将等待15秒再继续访问数据库,
    //此方法用一个dbLoop循环,使得等待时间超过5分钟将会输出错误
    private void init(){
    boolean connectionsSucceeded=false;
    int dbLoop=20;
    try{
    for(int i=0;i<dbLoop;i++){
    try{
    for(int j=1;j<currConnections;j++){
    createConn(j);
    }
    connectionsSucceeded=true;
    break;  //若每个连接都创建成功便跳出所有循环,初始化完毕。
    }catch(SQLException e){
    System.out.println("--->Attempt("+String.valueOf(i)+"of"+String.valueOf(dbLoop)+")failed to create new connections set at startup:");
    System.out.println("   "+e);
    System.out.println("   Will try again in 15 seconds...");
    e.printStackTrace();
    try{
    Thread.sleep(15000);//若创建某连接不成功,则等待15秒后继续尝试去连接数据库,本方法最外层的循环执行20次,表明最大的等待时间为15*20=5分钟。
    }catch(InterruptedException e1){e1.printStackTrace();}
    }
    }
    if(!connectionsSucceeded){
    //如果20次循环之后连接依然不能创建成功,证明等待数据库的重启时间已经超过5分钟,此时将输出提示错误信息。
    System.out.println("\r\nAll attempts at connecting to Database exhausted!");
    throw new IOException();
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    }

      

  2.   

    //下面该方法用于真正创建一个连接。
    private void createConn(int i) throws SQLException{
    Date now=new Date();
    try{
    Class.forName(dbdriver);
    connPool[i]=DriverManager.getConnection(dbserver,dbuser,dbpassword);
    connStatus[i]=0;
    connID[i]=connPool[i].toString();
    connLockTime[i]=0;
    connCreateTime[i]=0;
    connCreateTime[i]=now.getTime();
    }catch(ClassNotFoundException e2){
    e2.printStackTrace();
    throw new SQLException(e2.getMessage());
    }
    }
    //run()方法是本类最重要的方法,它有三个功能:
    //(1)它不断地获取连接过程中的警告信息并输出;
    //(2)它不断得测试每个连接的存在时间是否大于最大需重置的时间maxconnMSec,若大于则抛出异常进行重启;
    //(3)它不断地测试连接池中的连接是否存在问题,若存在问题便进行重启。

    public void run() {
    // TODO Auto-generated method stub
    Statement stmt=null;
    String surrCatalog=null;
    //线程执行无限循环,不断进行检查工作。
    for(;;){
    //下面这个循环用于获取连接过程中的警告信息。
    for(int i=0;i<currConnections;i++){
    try{
    currSQLWarning=connPool[i].getWarnings();
    if(currSQLWarning!=null){
    System.out.println("Warning on connection"+String.valueOf(i)+" "+currSQLWarning);
    connPool[i].clearWarnings();
    }
    }catch(SQLException e){
    System.out.println("Cannot access Warnings:"+e);
    }
    }
    for(int i=0;i<currConnections;i++){
    long age=System.currentTimeMillis()-connCreateTime[i];
    synchronized(connStatus){
    if(connStatus[i]>0)continue; //如果连接状态值大于0,表示它正在被使用,则下次再经进行测试。
    connStatus[i]=2; //如果连接状态是等于0,表示其处于空闲,则对他进行锁定,以便进行测试。
    }
    try{
    if(age>maxconnMSec){
    throw new SQLException();
    }
    stmt=connPool[i].createStatement();
    connStatus[i]=0; //获取stmt结果,使得连接处于开启状态,以进行下面的测试,stmt获取完便将连接的状态改为空闲。
    if(connPool[i].isClosed()){throw new SQLException();} //进行测试,如果连接处于关闭状态,说明这个连接存在问题,则抛出异常。
    }catch(SQLException e){
    try{
    connPool[i].close();
    createConn(i); //若连接存在问题,则重启连接。
    }catch(SQLException e1){
    System.out.println("Failed:"+e1);
    connStatus[i]=0;  //若连接存在问题又重启不了,则将其改为空闲状态,留到下次再检测。
    }
    }finally{
    try{
    if(stmt!=null)
    stmt.close();
    }catch(SQLException e1){};
    }
    }
    try {
    Thread.sleep(20000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
    } //检查完一个连接后等待20秒再进行下次检测
    }//end for(;;)
    }

    // getConnection()用来顺序获取连接池中的一个连接。
    public Connection getConnection(){
    Connection conn=null; //建立连接对象,用于后面赋值返回
    if(available){
    boolean getOne=false; //用于表示是否找到一个可用的连接。
    //下面这个循环执行10次,每次尝试从池中寻找一个连接,若10次都找不到一个连接,便返回null。
    for(int outerloop=1;outerloop<=10;outerloop++){
    try{
    int loop=0;   //用于记录在一个池中寻找失败的次数,若失败次数大于等于池中的连接数,则代表所有的连接都被使用。 
    int roundRobin=connLast+1; //记录所访问的连接的下标,若下标大于最大下标,则赋值为0,代表重新从第一个连接开始判断。
     //connLast表示上次所获取连接的下标,用connLast记录可以实现按顺序分配连接。
    if(roundRobin>=currConnections){
    roundRobin=0;
    }
    do{
    synchronized(connStatus){
    if((connStatus[roundRobin]<1)&&(!connPool[roundRobin].isClosed())){
    conn=connPool[roundRobin];
    connStatus[roundRobin]=1;
    connLockTime[roundRobin]=System.currentTimeMillis();
    connLast=roundRobin;
    getOne=true;
    break;
    }else{
    loop++;
    roundRobin++;
    if(roundRobin>=currConnections)roundRobin=0;
    }
    }
    }while((getOne==false)&&(loop<currConnections));
    }catch(SQLException e1){}
    if(getOne){break;}
    else{
    synchronized(this){
    if(currConnections<maxconns){
    try{
    createConn(currConnections);
    currConnections++;
    }catch(SQLException e){
    System.out.println("Unable to create new connection"+String.valueOf(currConnections-1));
    System.out.println("Exception :"+e);
    }

    }
    }

    try {
    Thread.sleep(2000); //执行完一次循环之后,若所有连接都被使用,则等待2秒再进行下一次的尝试。
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println("----->Connections Exhausted!Will wait and try"+"again in outer loop"+String.valueOf(outerloop));
    }
    }
    }else{
    System.out.println("Unsuccessful getConnection() request during destroy()"); //若available=0,表示连接池不可用,输出提示错误信息。
    }
    return conn;
    } public int idOfConnection(Connection conn){
    int match;
    String tag;
    try{
    tag=conn.toString(); //获取conn的标识
    }catch(NullPointerException e){tag="none";}
    match=-1;
    for(int i=0;i<currConnections;i++){
    if(connID[i].equals(tag)){
    match=i;  //如果连接池中包含conn所描述的连接,则返回其下标,若无,则返回-1。
    break;
    }
    }
    return match;
    }

    // freeConnection(conn)方法用于将conn是释放,返回到连接池中供其他连接所使用。
    public String freeConnection(Connection conn){
    String res="";
    int thisconn=idOfConnection(conn);
    if(thisconn>=0){
    connStatus[thisconn]=0; //若此连接有唯一标识,则利用其下标,将其状态改为空闲。
    res="freed"+conn.toString();
    }else{
    System.out.println("---->Could not free connection!!!"+"Try to close if directly");
    try {
    conn.close();
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    return res;
    }

    // 此方法用于返回某连接的寿命。
    public long getAge(Connection conn){
    int thisconn=idOfConnection(conn);
    return System.currentTimeMillis()-connLockTime[thisconn];
    }
        
    //此方法用于关闭后台线程,并在关闭millis时间后断开所有的连接
    public void destroy(int millis)throws SQLException{
    available=false;
    runner.interrupt();
    try {
    runner.join(millis);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    long startTime=System.currentTimeMillis();
    int useCount;
    while((useCount=getUseCount())>0&&System.currentTimeMillis()-startTime<=millis){
    try {
    Thread.sleep(500);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();

    }
    // 用一个循环,使得当前时间与方法开始调用的时间之差大于指定的millis之后,关闭所有连接。
    for(int i=0;i<currConnections;i++){
    connPool[i].close();
    }
    if(useCount>0){
    throw new SQLException();
    }
    }

    //默认销毁方法,millis值为10秒
    public void destroy(){
    try {
    destroy(10000);
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    //返回正在被使用的连接数。
    public int getUseCount(){
    int useCount=0;
    synchronized(connStatus){
    for(int i=0;i<currConnections;i++){
    if(connStatus[i]>0){
    useCount++;
    }
    }
    }
    return useCount;
    }

    //返回动态连接池中现有的连接数
    public int getSize(){
    return currConnections;
    }
    }//end class
      

  3.   

    这是一种连接池的java代码,上面的注释我写的很清楚了。使用的时候直接给它的构造函数赋值就行了,驱动方面的代码baidu有的下,sqlserver的驱动代码一般是com.microsoft.sqlserver.jdbc.SQLServerDriver,
    连接代码一般是jdbc:sqlserver://localhost:1433;DatabaseName=[name]。