一開始,選用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連接池,完全滿足了應用的需求,哈哈~~~
