最好能有一个守护线程,一个MaxFreeTime。守护线程可以在一个连接空闲达到MaxFreeTime时清除它。

解决方案 »

  1.   

    Far from good.Architecture wise:
    1. better make ConnectionPool an interface, and write the class as ConnectionPoolImpl, so that you can have more than one implementations of ConnectionPool2. getConnection(int timeout), better throw exception instead of returning null on timeout. "null" is always evil.3. should implement your own pool-version Connection so that the user can call Connection.close() rather than the freeConnection(). With freeConnection(), user may be able to pass the wrong connection to your pool (for example, the connection already in another pool. don't tell me it is singleton. in the future, it's possible you want to have more than one pool. Whether it is implemented as Singleton should be transparent to the user).Implementation issues and even bugs:1. may want to change notifyAll() to notify(). More efficient.2. getConnection has recursion in it. May want to change it to iteration.3. freeConn.removeElementAt(0); is most inefficient. might want to change it to freeConn.removeElementAt(freeConn.size()-1). or use List instead.4. static private ConnectionPool instance = new XXXX();
    static public ConnectionPool getInstance(){
    return instance;
    }
    this way, you save the synchronization cost for each getInstance() call. an empty ConnectionPool object is not big.5. getfreeconn(), getmaxconn(), getclient() should also be synchronized. Otherwise you may return stale state.
      

  2.   

    back off a little bit, getMaxConn() does not have to be synchronized.the same performance problem with the closeAllConn(). don't keep calling removeElementAt(0), it is O(n) operation.Here is a modified version, you need to write the two exception classes though:
    package zon100.dbconn;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.sql.*;
    import java.awt.*;
    import java.awt.image.*;public interface ConnectionPool{
        Connection getConnection()
        throw NoConnectionAvailableException;
        Connection getConnection(long timeout)
        throws TimeOutException;
        void clear();   
    }public class ConnectionPoolImpl implements ConnectionPool
    {
        static private ConnectionPool instance = new ConnectionPoolImpl();
        private int client;
        private String userName;
        private String passWord;
        private Vector freeConn = new Vector();
        private String dbURL;
        private int maxConn;
        private PrintWriter logPw;    static public ConnectionPool getInstance(){ return instance;}
        private ConnectionPool()
        {
            super();
            String logfile = "d://dbconn//log.log";
            userName = "system";
            passWord = "manager";
            dbURL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
            try
            {
                maxConn = Integer.parseInt("100");
            }
            catch(NumberFormatException e)
            {
                log("error in format number",e);
            }
            try
            {
                logPw = new PrintWriter(new FileWriter(logfile,true),true);
            }
            catch(IOException ioException)
            {
                //com.evoln.tool.file.PrintMessage("ConnectionPool.java","ConnectionPool","ConnectionFile",ioException.toString());
            }
            loadDrivers();
        }
        
        private void loadDrivers()
        {
            String driverName = "oracle.jdbc.driver.OracleDriver";
            try
            {
                //Driver driver = (Driver)Class.forName(driverName).newInstance();
                //DriverManager.registerDriver(driver);
                Class.forName(driverName);
                log("success in register driver: " + driverName);
            }
            catch(Exception e)
            {
                log("error in register driver: " + driverName,e);
            }
        }
        
        private void log(String message)
        {
            logPw.println( message);
        }    private void log(String message,Throwable e)
        {
            logPw.println(message + " " + e.toString()); 
        }
        
        //?????????????
        private synchronized void freeConnection(Connection conn)
        {
            freeConn.addElement(conn);
            client--;
            notify();
        }
        
        //???????????
        public synchronized Connection getConnection()
        throws NoConnectionAvailableException
        {
            Connection conn = null;
            if(freeConn.size() > 0)
            {
                conn = (Connection)freeConn.lastElement();
                freeConn.removeElementAt(freeConn.size()-1);
            }
            else if(client < maxConn)
            {
                conn = this.newConnection();
            }
            if(conn != null)
            {
                client++;
                return conn;
            }
            else
            {
                throw new NoConnectionAvailableException();
            }   
        }
            
        public synchronized Connection getConnection(long timeout)
        throws TimeOutException
        {
            for(long startTime = new java.util.Date().getTime();;)
            {
                try
                {
                    return getConnection();
                }
                catch(NoConnectionAvailableException e1)
                {
                    try
                    {
                        wait(timeout);
                    }
                    catch(InterruptedException e2)
                    {}
                    if((new java.util.Date().getTime() - startTime) >= timeout)
                    {
                        throw new TimeOutException();
                    }
                }
            }   
        }
        
        private Connection newConnection()
        {
            Connection conn = null;
            try
            {
                if(userName.equals(null))
                {
                    conn = DriverManager.getConnection(dbURL);
                }
                else
                {
                    conn = DriverManager.getConnection(dbURL,userName,passWord);
                }
            }
            catch(SQLException sqlException)
            {
                log("error in create new connection " ,sqlException);
            }
            return new PooledConnection(conn);
        }
        public synchronized int getfreeconn(){
            return freeConn.size();
        }
        public int getmaxConn(){
            return maxConn;
        }
        public synchronized int getclient(){
            return client;
        }
        public synchronized void setclient(){
            client=0;
        }
            
        public synchronized void clear(){
            for(int i=0; i<freeConn.size();i++)
            {
                final PooledConnection conn = (PooledConnection)freeConn.elementAt(i);
                final Connection conn2 = conn.getPooled();
                try{
                    conn2.close();
                }
                catch(SQLException sqlException){
                    log("error in close connection ",sqlException);
                }
            }
            freeConn.removeAllElements();
        }
        class PooledConnection implements Connection{
            private final Connection conn;
            private boolean closed;
            PooledConnection(Connection conn){
                this.conn = conn;
                closed = conn.isClosed();           
            }
            public public void close(){
                if(!closed){
                    closed = true;
                    freeConnection(this);
                }
            }
            public boolean isClosed(){
                return closed;
            }
            Connection getPooled(){return conn;}
            
            /*then, delegate all the other methods to conn. like*****************/
            public Statement createStatement()
            throws SQLException{
                return conn.createStatement();
            }
            public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
            throws SQLException{
                return conn.prepareStatement(sql, autoGeneratedKeys);
            }
            //....
            /*************************************************************************************************/
        }
    }
      

  3.   

    问个问题,我做ConnectionPool的时候从来都是指定MaxFreeConnection,而不是MaxConnection。MaxConnetion由一个Connection类(是个Interface,不同数据源独立实现)维护。然后就像我说的一样,有个守护线程关闭打到MaxFreeTime的连接。这样的话,有些数据源可以没有MaxConnection以对付一些大量突发的请求。而有的Connection自己本身在底层实现过Pool了。但是,好像别人都不这么做……(汗……)。这么做有什么问题吗?
      

  4.   

    Here's a refined version that compiles under java 1.1.8
    It uses your pooling logic behind. 
    There's space that you can enhance it. For example, the pool size, the upper limit, the lower limit, the username, password blah blah blah should be configurable. But that's different story though.//ConnectionPool.javapackage test.sql;
    import java.sql.Connection;
    import java.sql.SQLException;
    public interface ConnectionPool{
        Connection getConnection()
        throws NoConnectionAvailableException, SQLException;
        Connection getConnection(long timeout)
        throws TimeOutException, SQLException;
        void clear();
    }//TimeOutException.javapackage test.sql;
    import java.sql.SQLException;
    public class TimeOutException extends SQLException{
    public TimeOutException(String msg){super(msg);}
    public TimeOutException(){}
    }//NoConnectionAvailableException
    package test.sql;
    import java.sql.SQLException;
    public class NoConnectionAvailableException extends SQLException{
    public NoConnectionAvailableException(String msg){
                super(msg);
             }
    public NoConnectionAvailableException(){}
    }
      

  5.   

    //ConnectionPoolImpl.java
    package test.sql;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.DriverManager;
    import java.sql.DatabaseMetaData;
    import java.sql.SQLWarning;
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    //import java.sql.Savepoint;
    import java.util.Vector;
    //import java.util.Map;
    import java.io.PrintWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.sql.Statement;public class ConnectionPoolImpl implements ConnectionPool
    {
        static private final ConnectionPool instance = new ConnectionPoolImpl();
        private int client;
        private /*final*/ String userName;
        private /*final*/ String passWord;
        private final Vector freeConn = new Vector();
        private /*final*/ String dbURL;
        private /*final*/ int maxConn;
        private /*final*/ PrintWriter logPw;    static public ConnectionPool getInstance(){ return instance;}
        private ConnectionPoolImpl()
        {
            super();
            String logfile = "d://dbconn//log.log";
            userName = "system";
            passWord = "manager";
            dbURL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
            try
            {
                maxConn = Integer.parseInt("100");
            }
            catch(NumberFormatException e)
            {
                log("error in format number",e);
            }
            try
            {
                logPw = new PrintWriter(new FileWriter(logfile,true),true);
            }
            catch(IOException ioException)
            {
                //com.evoln.tool.file.PrintMessage("ConnectionPool.java","ConnectionPool","ConnectionFile",ioException.toString());
            }
            loadDrivers();
        }    private final void loadDrivers()
        {
            String driverName = "oracle.jdbc.driver.OracleDriver";
            try
            {
                //Driver driver = (Driver)Class.forName(driverName).newInstance();
                //DriverManager.registerDriver(driver);
                Class.forName(driverName);
                log("success in register driver: " + driverName);
            }
            catch(Exception e)
            {
                log("error in register driver: " + driverName,e);
            }
        }    private final void log(String message)
        {
            logPw.println( message);
        }    private final void log(String message,Throwable e)
        {
            logPw.println(message + " " + e.toString());
        }    //?????????????
        private final synchronized void freeConnection(Connection conn)
        {
            freeConn.addElement(conn);
            client--;
            notify();
        }    //???????????
        public final synchronized Connection getConnection()
        throws NoConnectionAvailableException, SQLException
        {
            Connection conn = null;
            if(freeConn.size() > 0)
            {
                conn = (Connection)freeConn.lastElement();
                freeConn.removeElementAt(freeConn.size()-1);
            }
            else if(client < maxConn)
            {
                conn = this.newConnection();
            }
            if(conn != null)
            {
                client++;
                return new PooledConnection(conn);
            }
            else
            {
                throw new NoConnectionAvailableException();
            }
        }    public final synchronized Connection getConnection(long timeout)
        throws TimeOutException, SQLException
        {
            for(long startTime = new java.util.Date().getTime();;)
            {
                try
                {
                    return getConnection();
                }
                catch(NoConnectionAvailableException e1)
                {
                    try
                    {
                        wait(timeout);
                    }
                    catch(InterruptedException e2)
                    {}
                    if((new java.util.Date().getTime() - startTime) >= timeout)
                    {
                        throw new TimeOutException();
                    }
                }
            }
        }    private final Connection newConnection()
        {
            Connection conn = null;
            try
            {
                if(userName.equals(null))
                {
                    conn = DriverManager.getConnection(dbURL);
                }
                else
                {
                    conn = DriverManager.getConnection(dbURL,userName,passWord);
                }
            }
            catch(SQLException sqlException)
            {
                log("error in create new connection " ,sqlException);
            }
            return conn;
        }
        public final synchronized int getfreeconn(){
            return freeConn.size();
        }
        public final int getmaxConn(){
            return maxConn;
        }
        public final synchronized int getclient(){
            return client;
        }
        public final synchronized void setclient(){
            client=0;
        }    public final synchronized void clear(){
            for(int i=0; i<freeConn.size();i++)
            {
                final Connection conn = (Connection)freeConn.elementAt(i);
                try{
                    conn.close();
                }
                catch(SQLException sqlException){
                    log("error in close connection ",sqlException);
                }
            }
            freeConn.removeAllElements();
        }    class PooledConnection implements Connection{
            interface ConnectionState{
                ConnectionState close()
                throws SQLException;
                boolean isClosed();
                Connection getOpenConnection()
                throws SQLException;
            }
            private ConnectionState state;
            class OpenConnection implements ConnectionState{
                private final Connection conn;
                public final ConnectionState close(){
                        freeConnection(conn);
                        return new ClosedConnection();
                }
                public final Connection getOpenConnection()
                {return conn;}
                public final boolean isClosed(){return false;}
                OpenConnection(Connection conn){this.conn = conn;}
            }
            class ClosedConnection implements ConnectionState{
                public final ConnectionState close(){return this;}
                public final Connection getOpenConnection()
                throws SQLException{
                    throw new SQLException("Connection closed");
                }
                public final boolean isClosed(){return true;}
                ClosedConnection(){}
            }
            PooledConnection(Connection conn)
            throws SQLException{
                if(conn.isClosed()){
                    state = new ClosedConnection();
                }
                else{
                    state = new OpenConnection(conn);
                }
            }       
            public final boolean isClosed(){
                return state.isClosed();
            }        public final void close()
            throws SQLException{
                state = state.close();
            }
            private final Connection getOpenConnection()
            throws SQLException
            {return state.getOpenConnection();}
            /*****then, delegate all the other methods****/
            public final Statement createStatement()
            throws SQLException{
                return getOpenConnection().createStatement();
            }
        
            public final void commit()throws SQLException{
                getOpenConnection().commit();
            }
    //......
            /******************************************/
                }
    }
      

  6.   

    further refined the ConnectionPoolImpl.java, here it is://PooledConnection.javapackage test.sql;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.DriverManager;
    import java.sql.DatabaseMetaData;
    import java.sql.SQLWarning;
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    //import java.sql.Savepoint;
    import java.util.Vector;
    //import java.util.Map;
    import java.io.PrintWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.sql.Statement;
    public class PooledConnection implements Connection{

    public interface Pool{
    void closeConnection(Connection conn);
    }
        private interface ConnectionState{
            ConnectionState close()
            throws SQLException;
            boolean isClosed();
            Connection getOpenConnection()
            throws SQLException;
        }
        private static class ClosedConnection implements ConnectionState{
            public final ConnectionState close(){return this;}
            public final Connection getOpenConnection()
            throws SQLException{
                throw new SQLException("Connection closed");
            }
            public final boolean isClosed(){return true;}
            private ClosedConnection(){}
            private static final ConnectionState _instance = new ClosedConnection();
            static ConnectionState instance(Connection conn, Pool pool){return _instance;}
        }
        
        private static class OpenConnection implements ConnectionState{
         private final Pool pool;
            private final Connection conn;
            public final ConnectionState close(){
                    pool.closeConnection(conn);
                    return ClosedConnection.instance(conn, pool);
            }
            public final Connection getOpenConnection()
            {return conn;}
            public final boolean isClosed(){return false;}
            OpenConnection(Connection conn, Pool pool){
             this.conn = conn; this.pool = pool;
            }
            static ConnectionState instance(Connection conn, Pool pool){
             return new OpenConnection(conn, pool);
            }
        }
        private ConnectionState state;
        public static Connection decorate(Connection conn, Pool pool)
        throws SQLException{
         return new PooledConnection(conn, pool);
        }
        
        private PooledConnection(Connection conn, Pool pool)
        throws SQLException{
            if(conn.isClosed()){
                state = ClosedConnection.instance(conn, pool);
            }
            else{
                state = OpenConnection.instance(conn, pool);
            }
        }       
        public final boolean isClosed(){
            return state.isClosed();
        }    public final void close()
        throws SQLException{
            state = state.close();
        }
        private final Connection getOpenConnection()
        throws SQLException
        {return state.getOpenConnection();}
        /*****then, delegate all the other methods****/
        public final Statement createStatement()
        throws SQLException{
            return getOpenConnection().createStatement();
        }
       
        //....
        public final void clearWarnings()throws SQLException{
            getOpenConnection().clearWarnings();
        }
          
     
        public final void commit()throws SQLException{
            getOpenConnection().commit();
        }
        
        public final boolean getAutoCommit()throws SQLException{
            return getOpenConnection().getAutoCommit();
        }
        public final String getCatalog()throws SQLException{
            return getOpenConnection().getCatalog();
        }      
        public final DatabaseMetaData getMetaData()throws SQLException{
            return getOpenConnection().getMetaData();
        }
        public final int getTransactionIsolation()throws SQLException{
            return getOpenConnection().getTransactionIsolation();
        }    public final SQLWarning getWarnings()throws SQLException{
            return getOpenConnection().getWarnings();
        }     public final boolean isReadOnly()throws SQLException{
            return getOpenConnection().isReadOnly();
        }
        public final String nativeSQL(String sql)throws SQLException{
            return getOpenConnection().nativeSQL(sql);
        }
        public final CallableStatement prepareCall(String sql)throws SQLException{
            return getOpenConnection().prepareCall(sql);
        }      
        public final PreparedStatement prepareStatement(String sql)
        throws SQLException{
            return getOpenConnection().prepareStatement(sql);
        }    public final void rollback()throws SQLException{
            getOpenConnection().rollback();
        }      
        public final void setAutoCommit(boolean autoCommit)
        throws SQLException{
            getOpenConnection().setAutoCommit(autoCommit);
        }
          
        public final void setCatalog(String catalog)
        throws SQLException{
            getOpenConnection().setCatalog(catalog);
        }
         
        public final void setReadOnly(boolean readOnly)
        throws SQLException{
            getOpenConnection().setReadOnly(readOnly);
        }      
        public final void setTransactionIsolation(int level)
        throws SQLException{
            getOpenConnection().setTransactionIsolation(level);
        }
        /*************************************************************************************************/
        }
      

  7.   

    then a simplified ConnectionPoolImpl:
    //ConnectionPoolImpl.javapackage test.sql;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.DriverManager;
    //import java.sql.Savepoint;
    import java.util.Vector;
    //import java.util.Map;
    import java.io.PrintWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    public class ConnectionPoolImpl implements ConnectionPool
    {
        static private final ConnectionPool instance = new ConnectionPoolImpl();
        private int client;
        private /*final*/ String userName;
        private /*final*/ String passWord;
        private final Vector freeConn = new Vector();
        private /*final*/ String dbURL;
        private /*final*/ int maxConn;
        private /*final*/ PrintWriter logPw;    static public ConnectionPool getInstance(){ return instance;}
        private ConnectionPoolImpl()
        {
            super();
            String logfile = "d://dbconn//log.log";
            userName = "system";
            passWord = "manager";
            dbURL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
            try
            {
                maxConn = Integer.parseInt("100");
            }
            catch(NumberFormatException e)
            {
                log("error in format number",e);
            }
            try
            {
                logPw = new PrintWriter(new FileWriter(logfile,true),true);
            }
            catch(IOException ioException)
            {
                //com.evoln.tool.file.PrintMessage("ConnectionPool.java","ConnectionPool","ConnectionFile",ioException.toString());
            }
            loadDrivers();
        }    private final void loadDrivers()
        {
            String driverName = "oracle.jdbc.driver.OracleDriver";
            try
            {
                //Driver driver = (Driver)Class.forName(driverName).newInstance();
                //DriverManager.registerDriver(driver);
                Class.forName(driverName);
                log("success in register driver: " + driverName);
            }
            catch(Exception e)
            {
                log("error in register driver: " + driverName,e);
            }
        }    private final void log(String message)
        {
            logPw.println( message);
        }    private final void log(String message,Throwable e)
        {
            logPw.println(message + " " + e.toString());
        }    //?????????????
        private final synchronized void freeConnection(Connection conn)
        {
            freeConn.addElement(conn);
            client--;
            notify();
        }    //???????????
        public final synchronized Connection getConnection()
        throws NoConnectionAvailableException, SQLException
        {
            Connection conn = null;
            if(freeConn.size() > 0)
            {
                conn = (Connection)freeConn.lastElement();
                freeConn.removeElementAt(freeConn.size()-1);
            }
            else if(client < maxConn)
            {
                conn = this.newConnection();
            }
            if(conn != null)
            {
                client++;
                return PooledConnection.decorate(conn, 
                 new PooledConnection.Pool(){
                 public void closeConnection(Connection conn){
                 freeConnection(conn);
                 }
                 });
            }
            else
            {
                throw new NoConnectionAvailableException();
            }
        }    public final synchronized Connection getConnection(long timeout)
        throws TimeOutException, SQLException
        {
            for(long startTime = new java.util.Date().getTime();;)
            {
                try
                {
                    return getConnection();
                }
                catch(NoConnectionAvailableException e1)
                {
                    try
                    {
                        wait(timeout);
                    }
                    catch(InterruptedException e2)
                    {}
                    if((new java.util.Date().getTime() - startTime) >= timeout)
                    {
                        throw new TimeOutException();
                    }
                }
            }
        }    private final Connection newConnection()
        {
            Connection conn = null;
            try
            {
                if(userName.equals(null))
                {
                    conn = DriverManager.getConnection(dbURL);
                }
                else
                {
                    conn = DriverManager.getConnection(dbURL,userName,passWord);
                }
            }
            catch(SQLException sqlException)
            {
                log("error in create new connection " ,sqlException);
            }
            return conn;
        }
        public final synchronized int getfreeconn(){
            return freeConn.size();
        }
        public final int getmaxConn(){
            return maxConn;
        }
        public final synchronized int getclient(){
            return client;
        }
        public final synchronized void setclient(){
            client=0;
        }    public final synchronized void clear(){
            for(int i=0; i<freeConn.size();i++)
            {
                final Connection conn = (Connection)freeConn.elementAt(i);
                try{
                    conn.close();
                }
                catch(SQLException sqlException){
                    log("error in close connection ",sqlException);
                }
            }
            freeConn.removeAllElements();
        }
    }
      

  8.   

    线程的问题就不说了
    这个最基本的:
    String logfile = "d://dbconn//log.log";
    这是你贴的代码中写的
    这样定义日志路径非常不方便
    你应该将类似这样的定义放到外部文件里
    然后在程序中读取该文件中定义的各参数。
      

  9.   

    String logfile = "d://dbconn//log.log";
    这个有什么问题呢,
    各个参数都是已经定义死了的,
    还要外部文件干嘛?
      

  10.   

    请问如何调用connection pool阿???
      

  11.   

    呵呵,同意。建议看看Resin自带的连接池,它是开源的。
      

  12.   

    select name,count(*) from table group by name having count(*)>1
    ___________________________________________________________________
          苦闷中…………………………
    ___________________________________________________________________