java 简单 SocketPool
package org.rx.socks; import lombok.extern.slf4j.Slf4j;
import org.rx.common.LogWriter;
import org.rx.common.NQuery;
import org.rx.beans.DateTime; import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket; import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque; import static org.rx.common.Contract.require; @Slf4j
public final class SocketPool extends Traceable implements AutoCloseable {
public static final class PooledSocket implements AutoCloseable {
private final SocketPool owner;
private DateTime lastActive;
public final Socket socket; public boolean isConnected() {
return !owner.isClosed() && !socket.isClosed() && socket.isConnected();
} public DateTime getLastActive() {
return lastActive;
} public void setLastActive(DateTime lastActive) {
this.lastActive = lastActive;
} private PooledSocket(SocketPool owner, Socket socket) {
this.owner = owner;
this.socket = socket;
lastActive = DateTime.utcNow();
} @Override
public void close() {
owner.returnSocket(this);
}
} public static final SocketPool Pool = new SocketPool();
private static final int DefaultConnectTimeout = 30000;
private static final int DefaultMaxIdleMillis = 120000;
private static final int DefaultMaxSocketsCount = 64;
private final ConcurrentHashMap<InetSocketAddress, ConcurrentLinkedDeque<PooledSocket>> pool;
private volatile int connectTimeout;
private volatile int maxIdleMillis;
private volatile int maxSocketsCount;
private final Timer timer;
private volatile boolean isTimerRun; public int getConnectTimeout() {
return connectTimeout;
} public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
} public int getMaxIdleMillis() {
return maxIdleMillis;
} public void setMaxIdleMillis(int maxIdleMillis) {
if (maxIdleMillis <= 0) {
maxIdleMillis = DefaultMaxIdleMillis;
}
this.maxIdleMillis = maxIdleMillis;
} public int getMaxSocketsCount() {
return maxSocketsCount;
} public void setMaxSocketsCount(int maxSocketsCount) {
if (maxSocketsCount < 0) {
maxSocketsCount = 0;
}
this.maxSocketsCount = maxSocketsCount;
} private SocketPool() {
pool = new ConcurrentHashMap<>();
connectTimeout = DefaultConnectTimeout;
maxIdleMillis = DefaultMaxIdleMillis;
maxSocketsCount = DefaultMaxSocketsCount;
String n = "SocketPool";
timer = new Timer(n, true);
LogWriter tracer = new LogWriter();
tracer.setPrefix(n + " ");
tracer.info("started..");
setTracer(tracer);
} @Override
protected void freeObjects() {
clear();
} private void runTimer() {
if (isTimerRun) {
return;
}
synchronized (timer) {
if (isTimerRun) {
return;
} long period = 90000;
timer.schedule(new TimerTask() {
@Override
public void run() {
clearIdleSockets();
}
}, period, period);
isTimerRun = true;
}
getTracer().info("runTimer..");
} private void clearIdleSockets() {
for (Map.Entry<InetSocketAddress, ConcurrentLinkedDeque<PooledSocket>> entry : NQuery.of(pool.entrySet())) {
ConcurrentLinkedDeque<PooledSocket> sockets = entry.getValue();
if (sockets == null) {
continue;
} for (PooledSocket socket : NQuery.of(sockets)) {
if (!socket.isConnected()
|| DateTime.utcNow().subtract(socket.getLastActive()).getTotalMilliseconds() >= maxIdleMillis) {
sockets.remove(socket);
getTracer().info("clear idle socket[local=%s, remote=%s]..",
Sockets.getId(socket.socket, false), Sockets.getId(socket.socket, true));
}
}
if (sockets.isEmpty()) {
pool.remove(entry.getKey());
}
}
if (pool.size() == 0) {
stopTimer();
}
} private void stopTimer() {
synchronized (timer) {
timer.cancel();
timer.purge();
isTimerRun = false;
}
getTracer().info("stopTimer..");
} private ConcurrentLinkedDeque<PooledSocket> getSockets(InetSocketAddress remoteAddr) {
ConcurrentLinkedDeque<PooledSocket> sockets = pool.get(remoteAddr);
if (sockets == null) {
pool.put(remoteAddr, sockets = new ConcurrentLinkedDeque<>());
runTimer();
}
return sockets;
} public PooledSocket borrowSocket(InetSocketAddress remoteAddr) {
checkNotClosed();
require(remoteAddr); boolean isExisted = true;
ConcurrentLinkedDeque<PooledSocket> sockets = getSockets(remoteAddr);
PooledSocket pooledSocket;
if ((pooledSocket = sockets.pollFirst()) == null) {
Socket sock = new Socket();
try {
sock.connect(remoteAddr, connectTimeout);
} catch (IOException ex) {
throw new SocketException(remoteAddr, ex);
}
pooledSocket = new PooledSocket(this, sock);
isExisted = false;
}
if (!pooledSocket.isConnected()) {
if (isExisted) {
sockets.remove(pooledSocket);
}
return borrowSocket(remoteAddr);
}
Socket sock = pooledSocket.socket;
getTracer().info("borrow %s socket[local=%s, remote=%s]..", isExisted ? "existed" : "new",
Sockets.getId(sock, false), Sockets.getId(sock, true));
return pooledSocket;
} public void returnSocket(PooledSocket pooledSocket) {
checkNotClosed();
require(pooledSocket); String action = "return";
try {
if (!pooledSocket.isConnected()) {
action = "discard closed";
return;
}
pooledSocket.setLastActive(DateTime.utcNow());
ConcurrentLinkedDeque<PooledSocket> sockets = getSockets(
(InetSocketAddress) pooledSocket.socket.getRemoteSocketAddress());
if (sockets.size() >= maxSocketsCount || sockets.contains(pooledSocket)) {
action = "discard contains";
return;
} sockets.addFirst(pooledSocket);
} finally {
Socket sock = pooledSocket.socket;
getTracer().info("%s socket[local=%s, remote=%s]..", action, Sockets.getId(sock, false),
Sockets.getId(sock, true));
}
} public void clear() {
checkNotClosed(); for (Socket socket : NQuery.of(pool.values()).selectMany(p -> p).select(p -> p.socket)) {
try {
getTracer().info("clear socket[local=%s, remote=%s]..", Sockets.getId(socket, false),
Sockets.getId(socket, true));
Sockets.close(socket);
} catch (Exception ex) {
log.error("SocketPool clear", ex);
}
}
pool.clear();
}
}
java 简单 SocketPool的更多相关文章
- java简单词法分析器(源码下载)
java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ...
- !!转!!java 简单工厂模式
举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就是 ...
- JAVA简单Swing图形界面应用演示样例
JAVA简单Swing图形界面应用演示样例 package org.rui.hello; import javax.swing.JFrame; /** * 简单的swing窗体 * @author l ...
- 多元线性回归----Java简单实现
http://www.cnblogs.com/wzm-xu/p/4062266.html 多元线性回归----Java简单实现 学习Andrew N.g的机器学习课程之后的简单实现. 课程地址:h ...
- java简单数据类型转化
java简单数据类型,有低级到高级为:(byte,short,char)→int→long→float→double (boolean不参与运算转化) 转化可以分为 低级到高级的自动转化 高级到低级的 ...
- 预防和避免死锁的方法及银行家算法的java简单实现
预防死锁 (1) 摒弃"请求和保持"条件 基本思想:规定所有进程在开始运行之前,要么获得所需的所有资源,要么一个都不分配给它,直到所需资源全部满足才一次性分配给它. 优点:简单.易 ...
- Java简单聊天室
实现Java简单的聊天室 所用主要知识:多线程+网络编程 效果如下图 /** * * @author Administrator * * 简单的多人聊天系统——重点:同时性,异步性 * 1.客户端:发 ...
- Java简单工厂模式
Java简单工厂模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式.简 ...
- java简单web爬虫(网页图片)
java简单web爬虫(网页图片)效果,执行main()方法后图片就下载道C盘的res文件夹中.没有的话创建一个文件夹代码里的常量根据自己的需求修改,代码附到下面. package com.sinit ...
随机推荐
- SQL语句之-计算字段/分组
五.计算字段 1.拼接字段 MySQL:使用函数concat SqlServer:使用加号+ oracle:使用|| SELECT CONCAT(vend_name,'(',vend_country, ...
- (转)Maven中的库(repository)详解 ---repository配置查找构件(如.jar)的远程库
转:https://blog.csdn.net/taiyangdao/article/details/52287856 Maven中的库(repository)是构件(artifact)的集合.构件以 ...
- cassandra百亿级数据库迁移实践
迁移背景 cassandra集群隔段时间出现rt飙高的问题,带来的影响就是请求cassandra短时间内出现大量超时,这个问题发生已经达到了平均两周一次的频率,已经影响到正常业务了.而出现这些问题的原 ...
- appium自动化测试- 元素操作
本文转自:https://www.cnblogs.com/sinder2018/articles/9699801.html 一.滑动屏幕 1.appium - 滑动屏幕 滑动接口: swipe(起始X ...
- 通过HttpServletResponseWrapper修改response输出流
在项目中遇到一个问题,需要对接口返回的数据进行加密给前端.项目中的controller一般都是返回一个实体form,重写的一个视图解析器继承ModelAndViewResolver,对返回的form转 ...
- 大数据学习之BigData常用算法和数据结构
大数据学习之BigData常用算法和数据结构 1.Bloom Filter 由一个很长的二进制向量和一系列hash函数组成 优点:可以减少IO操作,省空间 缺点:不支持删除,有 ...
- select change()
$(".learnStageId").change(function(){ var id = $(this).val(); $(".gradeId").find ...
- 14. Django MTV及Django模型
MTV 我们或许都听说过MVC模式.MVC是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码.Django ...
- overflow:hidden失效
overflow:hidden失效 为了页面的健壮性,我们常常需要使用overflow:hidden.有时候是为了防止布局被撑开,有时候是为了配合其它规则实现文字截断,还有时候纯粹是为了创建块级上下文 ...
- 13-python基础—python3中的map()
map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表. 通俗解释: m ...