構建簡單的socket連接池


一開始,選用Vector<E>來存放連接。由於這個容器不是並發安全的,於是,每個方法都加一個synchronized來保持並發時的同步操作,並發效率很差,果斷放棄。空余時間研究了下多線程的並發知識,決定用並發安全的阻塞隊列(LinkedBlockingQueue<E>),這個容器可以自動維護容量的大小,就免去了再起一個線程去維護線程池的大小。為了保證每個連接是可用的,為線程池啟動了一個守護線程去定時發送心跳。

程序如下,歡迎高手們指點缺陷:

  1 public class SocketConnectionPool {
  2 
  3     private ConnectionPoolConfig poolConfig; // 連接池配置
  4     private LinkedBlockingQueue<SocketConnection> freeConnections; // 空閑池連接
  8     
  9     public ConnectionPoolConfig getPoolConfig() {
 10         return poolConfig;
 11     } 21     public LinkedBlockingQueue<SocketConnection> getFreeConnections() {
 22         return freeConnections;
 23     }
 24     /**
 25      * 功能描述:連接池構造方法
 26      * 
 27      * @author mihu
 28      * @version mihu
 29      * @param config
 30      * @throws UnknownHostException
 31      * @throws IOException
 32      */
 33     public SocketConnectionPool(ConnectionPoolConfig config){
 34         try {
 35             if(config == null){
 36                 log.error("func[init] ConnectionPoolConfig is null ......");
 37                 return;
 38             }
 39             
 40             this.poolConfig = config;
 41             this.freeConnections = new LinkedBlockingQueue<SocketConnection>(config.getMaxConn());  //構造指定大小的阻塞隊列
 42             
 43             init();
 44             
 45         } catch (UnknownHostException e) {
 46             e.printStackTrace();
 47         } catch (ConnectException e){
 48             e.printStackTrace();
 49         } catch (SocketTimeoutException e){
 50             e.printStackTrace();
 51         } catch (IOException e) {
 52             e.printStackTrace();
 53         } catch (Exception e) {
 54             e.printStackTrace();
 55         } finally{
 56             
 57             //心跳檢測守護線程
 58             if(config != null){
 59                 ACheckThread aCheckThread = new ACheckThread(this);
 60                 aCheckThread.setDaemon(true);
 61                 aCheckThread.start();
 62             }
 63         }
 64     }
 65     
 66     /**
 67      * 功能描述:初始化連接池
 68      * 
 69      * @return
 70      * @throws UnknownHostException
 71      * @throws IOException 
 72      * @author mihu
 73      * @version mihu
 74      * @throws InterruptedException 
 75      * @since 2013-7-2
 76      *
 77      */
 78     public void init() throws UnknownHostException, IOException,SocketTimeoutException,ConnectException, InterruptedException{
 79         
 80         for(int i=0; i<poolConfig.getMinConn(); i++){
 81             SocketConnection client = new SocketConnection(poolConfig.getHost(), poolConfig.getPort());
 82             freeConnections.offer(client);
 83         }
 84         
 85     }
 86     
 87     /**
 88      * 功能描述:新建連接
 89      * 
 90      * @param totalConnSize
 91      * @throws UnknownHostException
 92      * @throws IOException 
 93      * @author mihu
 94      * @version mihu
 95      * @since 2013-7-2
 96      *
 97      */
 98     public SocketConnection newConnection() throws UnknownHostException, IOException{
 99         SocketConnection client = new SocketConnection(this.poolConfig.getHost(), this.poolConfig.getPort());
100         
101         return client;
102     }
103     
104     /**
105      * 功能描述:獲取連接
106      * 
107      * @return SocketConnection連接
108      * @throws UnknownHostException
109      * @throws IOException 
110      * @author mihu
111      * @version mihu
112      * @throws InterruptedException 
113      * @since 2013-7-2
114      *
115      */
116     public SocketConnection getConnection() throws UnknownHostException, IOException, InterruptedException{
117         if(freeConnections.size()==0){
118             synchronized (freeConnections) {
119                 int freeConnCount = freeConnections.size();
120                 if(freeConnCount == 0 && freeConnCount < this.poolConfig.getMaxConn()){
121                     SocketConnection client = newConnection();
122                     return client;
123                 }
124             }
125         }
126         
127         SocketConnection client = freeConnections.poll(2000,TimeUnit.MILLISECONDS);
128         
129         return client;
130     }
131     
132     
133     /**
134      * 功能描述:將連接還回連接池
135      * 
136      * @param client
137      * @throws IOException 
138      * @author mihu
139      * @version mihu
140      * @throws InterruptedException 
141      * @since 2013-7-2
142      *
143      */
144     public void freeConnection(SocketConnection client) throws IOException, InterruptedException{
145         if(null != client && !client.isClosed()){
146             freeConnections.offer(client);
147         }
148     }
149     
150 }

 以上連接池的代碼已經被廢棄了,多線程下問題多多。

 某天在網上看到數據庫連接池的開源代碼boneCP,據說是當前最高效的數據庫連接池。於是下載了它的源碼學習了一番,發現它的代碼簡潔,可閱讀性強,沒有過多的使用鎖機制來避免臨界競爭,這一點和c3p0很不同。

 最后根據boneCP的思維重構了自己的socket連接池,完全滿足了應用的需求,哈哈~~~

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM