构建简单的socket连接池
一开始,选用Vector<E>来存放连接。由于这个容器不是并发安全的,于是,每个方法都加一个synchronized来保持并发时的同步操作,并发效率很差,果断放弃。空余时间研究了下多线程的并发知识,决定用并发安全的阻塞队列(LinkedBlockingQueue<E>),这个容器可以自动维护容量的大小,就免去了再起一个线程去维护线程池的大小。为了保证每个连接是可用的,为线程池启动了一个守护线程去定时发送心跳。
程序如下,欢迎高手们指点缺陷:
 public class SocketConnectionPool {
     private ConnectionPoolConfig poolConfig; // 连接池配置
     private LinkedBlockingQueue<SocketConnection> freeConnections; // 空闲池连接
     public ConnectionPoolConfig getPoolConfig() {
         return poolConfig;
     }     public LinkedBlockingQueue<SocketConnection> getFreeConnections() {
         return freeConnections;
     }
     /**
      * 功能描述:连接池构造方法
      *
      * @author mihu
      * @version mihu
      * @param config
      * @throws UnknownHostException
      * @throws IOException
      */
     public SocketConnectionPool(ConnectionPoolConfig config){
         try {
             if(config == null){
                 log.error("func[init] ConnectionPoolConfig is null ......");
                 return;
             }
             this.poolConfig = config;
             this.freeConnections = new LinkedBlockingQueue<SocketConnection>(config.getMaxConn());  //构造指定大小的阻塞队列
             init();
         } catch (UnknownHostException e) {
             e.printStackTrace();
         } catch (ConnectException e){
             e.printStackTrace();
         } catch (SocketTimeoutException e){
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
         } finally{
             //心跳检测守护线程
             if(config != null){
                 ACheckThread aCheckThread = new ACheckThread(this);
                 aCheckThread.setDaemon(true);
                 aCheckThread.start();
             }
         }
     }
     /**
      * 功能描述:初始化连接池
      *
      * @return
      * @throws UnknownHostException
      * @throws IOException
      * @author mihu
      * @version mihu
      * @throws InterruptedException
      * @since 2013-7-2
      *
      */
     public void init() throws UnknownHostException, IOException,SocketTimeoutException,ConnectException, InterruptedException{
         for(int i=0; i<poolConfig.getMinConn(); i++){
             SocketConnection client = new SocketConnection(poolConfig.getHost(), poolConfig.getPort());
             freeConnections.offer(client);
         }
     }
     /**
      * 功能描述:新建连接
      *
      * @param totalConnSize
      * @throws UnknownHostException
      * @throws IOException
      * @author mihu
      * @version mihu
      * @since 2013-7-2
      *
      */
     public SocketConnection newConnection() throws UnknownHostException, IOException{
         SocketConnection client = new SocketConnection(this.poolConfig.getHost(), this.poolConfig.getPort());
         return client;
     }
     /**
      * 功能描述:获取连接
      *
      * @return SocketConnection连接
      * @throws UnknownHostException
      * @throws IOException
      * @author mihu
      * @version mihu
      * @throws InterruptedException
      * @since 2013-7-2
      *
      */
     public SocketConnection getConnection() throws UnknownHostException, IOException, InterruptedException{
         if(freeConnections.size()==0){
             synchronized (freeConnections) {
                 int freeConnCount = freeConnections.size();
                 if(freeConnCount == 0 && freeConnCount < this.poolConfig.getMaxConn()){
                     SocketConnection client = newConnection();
                     return client;
                 }
             }
         }
         SocketConnection client = freeConnections.poll(2000,TimeUnit.MILLISECONDS);
         return client;
     }
     /**
      * 功能描述:将连接还回连接池
      *
      * @param client
      * @throws IOException
      * @author mihu
      * @version mihu
      * @throws InterruptedException
      * @since 2013-7-2
      *
      */
     public void freeConnection(SocketConnection client) throws IOException, InterruptedException{
         if(null != client && !client.isClosed()){
             freeConnections.offer(client);
         }
     }
 }
以上连接池的代码已经被废弃了,多线程下问题多多。
某天在网上看到数据库连接池的开源代码boneCP,据说是当前最高效的数据库连接池。于是下载了它的源码学习了一番,发现它的代码简洁,可阅读性强,没有过多的使用锁机制来避免临界竞争,这一点和c3p0很不同。
最后根据boneCP的思维重构了自己的socket连接池,完全满足了应用的需求,哈哈~~~
构建简单的socket连接池的更多相关文章
- 用swoole简单实现MySQL连接池
		
MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...
 - Go语言之从0到1实现一个简单的Redis连接池
		
Go语言之从0到1实现一个简单的Redis连接池 前言 最近学习了一些Go语言开发相关内容,但是苦于手头没有可以练手的项目,学的时候理解不清楚,学过容易忘. 结合之前组内分享时学到的Redis相关知识 ...
 - 自定义一个简单的JDBC连接池
		
一.什么是JDBC连接池? 在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码: public static Connection getCo ...
 - 转  Swoole】用swoole简单实现MySQL连接池
		
MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...
 - Redisclient连接方式Hiredis简单封装使用,连接池、屏蔽连接细节
		
工作须要对Hiredis进行了简单封装,实现功能: 1.API进行统一,对外仅仅提供一个接口. 2.屏蔽上层应用对连接的细节处理: 3.底层採用队列的方式保持连接池,保存连接会话. 4.重连时採用时间 ...
 - 利用python list 完成最简单的DB连接池
		
先来看查看效果: 在代码连接数据库后,并且执行三条sql后,将mysql直接重启掉,故我们的连接池连接均是不ok的,所以,它会全部删除再抓新的连接下来,重启mysql命令: 关于python代码: # ...
 - 简单使用c3p0连接池
		
首先,c3p0是一个连接池插件 需要jar包: 使用手动配置: /** * 手动配置使用c3p0 * @throws PropertyVetoException * @throws SQLExcept ...
 - Redis 简单使用 and 连接池(python)
		
Redis 简介 NoSQL(not only sql):非关系型数据库 支持 key-value, list, set, zset, hash 等数据结构的存储:支持主从数据备份,集群:支持 ...
 - 1.1最简单的socket连接
		
socket 服务器代码 # -*- coding: utf-8 -*-from socket import * myHost = '' #''说明所有IP都可以连接 myPort = 50007 # ...
 
随机推荐
- 阿里巴巴SUI Mobile的使用
			
1.引入文件 <link rel="stylesheet" href="./css/sm.min.css"> <link rel=" ...
 - Retrofit 2.0 throwing @Field parameters can only be used with form encoding
			
最近在学习Retrofit2.0想用Retrofit + Dagger2 + RxJava + ButterKnife一起使用重构项目 一方面自己的demo随着业务逻辑的增多 显得非常的乱 另一方面代 ...
 - QT学习(对话框)codeblock版本
			
参考: http://www.cnblogs.com/JohnShao/archive/2011/09/26/2191627.html http://www.cnblogs.com/xiao-chen ...
 - VS2010+WINDBG+VMWARE9.0和fatal error RC1106: invalid option: -ologo错误
			
提供属性配置文件一份: http://pan.baidu.com/s/1iS1Ix <?xml version="1.0" encoding="utf-8" ...
 - 如何使用Visual Studio 2013 创建Azure云应用
			
创建 Azure 云服务 Azure 云服务包括执行应用程序所需操作的角色.当你将云服务发布到 Azure 时,每个角色将在云中的虚拟机上运行.有关如何开发 Azure 云服务的详细信息. 创建 Az ...
 - PHP使用SwiftMailer发送邮件
			
用到了swiftmailer 的lib库 官方网址:http://swiftmailer.org/ require_once 'lib/swift_required.php';//给我发送邮件func ...
 - HDU4417 - Super Mario(主席树)
			
题目大意 给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 题解 和静态的区间第K大差不多,这题是<=K,先建立好n颗主席树,然后用第R颗主席树区间[1,K]内数的数量减去第L-1 ...
 - Redis以及Redis的php扩展安装无错版
			
安装Redis 下载最新的 官网:http://redis.io/ 或者 http://code.google.com/p/redis/downloads/list 第一步:下载安装编译 #wge ...
 - YII访问数据库
			
YII访问数据库 CDbConnection: 一个抽象数据库连接 CDbCommand: SQL statement CDbDataReader: 匹配结果集的一行记录 CDbTransaction ...
 - EF搜索数据自动将表名变复数问题
			
原因这个是自己生成的需要在model加Table 其他博主写了aweier2011