构建简单的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 # ...
随机推荐
- bzoj1492
好题+神题,首先肯定是dp,我们设f[i]为到第i天能获得的最多的B卷(设获得的钱数亦可)由题目hint可知,要么全买要么全卖,我们有f[i]=max(maxmoney,f[j]*b[i]+f[j]* ...
- bat中的连接符
& [...] command1 & command2 用来分隔一个命令行中的多个命令.Cmd.exe 运行第一个命令,然后运行第二个命令. && [...] comm ...
- App.config提示错误“配置系统未能初始化”
解决: "如果配置文件中包含 configSections 元素,则 configSections 元素必须是 configuration 元素的第一个子元素." 所以它前面如果有 ...
- [OpenSource]浅谈.Net和Java互相调用的三种方式
在很多的大型系统开发中,开发工具往往不限制于同一种开发语言,而是会使用多种开发语言的混合型开发.目前Java和.Net都声称自己占85%的市场份额,不管谁对谁错,Java和.Net是目前应用开发的两个 ...
- Linux下的iwpriv(iwlist、iwconfig)的简单应用
无线网络飞速发展的今天,许多设备都提供了连接无线网络的功能. 那么Linux下的wifi到底该怎么配置.连接呢?? 开始配置之前,我们要说说iw家族.iw是linux下常用的wifi配置工具,网上有相 ...
- Nginx实现七层负载均衡配置指导
本文描述了如何使用Nginx实现在应用层实现7层负载均衡功能,Nginx支持虚拟主机,可以按照轮询,IP哈希,URL哈希,权重方式对后端服务器做负载均衡,还支持后端服务器健康检查功能.废话不多说,详细 ...
- 解决Mac下Sequel Pro 1.1 连接 Homebrew安装Mysql5.7.8的问题 Sequel Pro 1.1 encountered an unexpected error
解决Mac下Sequel Pro 1.1 连接 Homebrew安装Mysql5.7.8的问题 Sequel Pro encountered an unexpected error Sequel Pr ...
- iOS真机调试——申请开发者证书
申请开发者证书 知道了什么是证书,我们现在就开始申请证书了 1. 找到KeyChain钥匙串,在Mac应用里可以找到 2. 在钥匙串的菜单中选择从证书颁发机构请求证书,填写邮件地址,选择储存到磁盘,放 ...
- shell脚本应用(3)--语法结构
判断语句 条件判断 test expression [ expression ] 条件表达式中常用的判断 数值-eq -ne -gt -lt -ge -le[equal not greater tha ...
- android onTouch()与onTouchEvent()的区别
1.onTouch方法: onTouch方法是View的 OnTouchListener借口中定义的方法.当一个View绑定了OnTouchLister后,当有touch事件触发时,就会调用onTou ...