有意思,我昨天刚写了一个socket连接池。
- 没有要检查的守护线程。
- 它将检查被动以尝试建立连接
- connection.isClosed 会检查socket状态,当然不可靠
- 检查连接是否过期
- 它将检查是否返回连接。您必须在使用异常时将连接标记为已关闭。
/** * @author:xingchaowang * @date: 8/14/2014. */
公共类 ConnectionPoolImpl 实现 ConnectionPool {
private volatile int minConnections;
private volatile int maxConnections;
private volatile long connectionTTL;
private volatile long leaseTimeout = 1000;
private AtomicInteger pending = new AtomicInteger(0);
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private LinkedList<Connection> free = new LinkedList<Connection>();
private Set<Connection> leased = new HashSet<Connection>();
private ConnectionFactory connectionFactory;
public ConnectionPoolImpl(int minConnections, int maxConnections, long connectionTTL, long leaseTimeout, ConnectionFactory connectionFactory) {
this.minConnections = minConnections;
this.maxConnections = maxConnections;
this.connectionTTL = connectionTTL;
this.leaseTimeout = leaseTimeout;
this.connectionFactory = connectionFactory;
}
@Override
public Connection lease() throws Exception {
return lease(1000);
}
@Override
public Connection lease(long timeout) throws Exception {
pending.incrementAndGet();
lock.lock();
try {
Connection connection = null;
Date deadLine = new Date(System.currentTimeMillis() + timeout);
while (true) {
long now = System.currentTimeMillis();
//If the count of existing connections is less than minConnections, create new one and return.
if (_connectionCount() < minConnections) {
return _createAndLease();
}
//Try to get a connection from the free list.
while ((connection = free.pollFirst()) != null) {
if (connection.isClosed()) {
continue;
} else if (connection.getCreatedTime() + connectionTTL < now) {
connection.close();
}else{
leased.add(connection);
return connection;
}
}
//Free list is empty, try to create new one if doesn't reach the upper limit maxConnections.
if (_connectionCount() < maxConnections) {
return _createAndLease();
}
condition.awaitUntil(deadLine);
//Try to get again if doesn't reach the deadLine, or return by throwing a TimeoutException.
if (deadLine.getTime() >= System.currentTimeMillis()) {
throw new TimeoutException("Timeout waiting for connection");
}
}
} finally {
lock.unlock();
pending.decrementAndGet();
}
}
@Override
public void release(Connection connection) {
lock.lock();
try{
long now = System.currentTimeMillis();
leased.remove(connection);
if (connection.isClosed()) {
return;
} else if (connection.getCreatedTime() + connectionTTL < now) {
connection.close();
}else{
free.add(connection);
}
}finally {
condition.signal();
lock.unlock();
}
}
@Override
public PoolStats poolStats() {
return new PoolStats(leased.size(),free.size(),pending.get(),minConnections,maxConnections);
}
private int _connectionCount() {
return free.size() + leased.size();
}
private Connection _createAndLease() throws Exception {
Connection connection;
connection = connectionFactory.create();
leased.add(connection);
return connection;
}
public int getMinConnections() {
return minConnections;
}
public void setMinConnections(int minConnections) {
this.minConnections = minConnections;
}
public int getMaxConnections() {
return maxConnections;
}
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
public long getConnectionTTL() {
return connectionTTL;
}
public void setConnectionTTL(long connectionTTL) {
this.connectionTTL = connectionTTL;
}
public long getLeaseTimeout() {
return leaseTimeout;
}
public void setLeaseTimeout(long leaseTimeout) {
this.leaseTimeout = leaseTimeout;
}
}