构建简单的socket连接池
前奏:这段时间,公司安排了一个任务:构建一个管理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 }