Created
November 10, 2023 17:07
-
-
Save hsynercn/b9a69b3810b1d0648f8ff564b1c25752 to your computer and use it in GitHub Desktop.
ConnectionPool.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Queue; | |
import java.util.stream.Collectors; | |
public class ConnectionPool { | |
private static final int RESOURCE_RETRIEVAL_TRY_COUNT = 10; | |
private static final int RESOURCE_RETRIEVAL_WAIT_PERIOD = 1000; | |
private static final int POOL_SIZE = 10; | |
private final Queue<Connection> connectionPool = new LinkedList<>(); | |
private int uninitializedConnectionCount; | |
private String connectionParameter; | |
private Exception createException; | |
private final Object resourceRetrievalLock = new Object(); | |
public ConnectionPool(String connectionParameter) { | |
this.connectionParameter = connectionParameter; | |
List<Connection> connections = this.createResource(POOL_SIZE); | |
synchronized (connectionPool) { | |
this.connectionPool.addAll(connections); | |
this.uninitializedConnectionCount = POOL_SIZE - connections.size(); | |
} | |
} | |
public final List<Connection> createResource(int resourceCount) { | |
ArrayList<Integer> list = new ArrayList<>(); | |
for (int i = 0; i < resourceCount; i++) { | |
list.add(i); | |
} | |
Exception resourceCreationExTemp = null; | |
List<ConnCreationResult> createdConnectionsAll = list.parallelStream() | |
.map((Integer item) -> { | |
ConnCreationResult result = null; | |
try { | |
Connection newConnection = new Connection(this.connectionParameter); | |
result = new ConnCreationResult(newConnection, null); | |
} catch (Exception ex) { | |
//we store resource creation exceptions | |
result = new ConnCreationResult(null, ex); | |
} | |
return result; | |
}) | |
.collect(Collectors.toList()); | |
LinkedList<Connection> resultList = new LinkedList<>(); | |
for (ConnCreationResult connCreationResult : createdConnectionsAll) { | |
if (connCreationResult.getConnection() != null) { | |
resultList.add(connCreationResult.getConnection()); | |
} else { | |
resourceCreationExTemp = connCreationResult.getException(); | |
} | |
} | |
this.createException = resourceCreationExTemp; | |
return resultList; | |
} | |
public synchronized boolean checkConnections() { | |
try { | |
int currentUninitializedConnectionCount = 0; | |
synchronized (connectionPool) { | |
LinkedList<Connection> aliveConnectionPool = new LinkedList<>(); | |
aliveConnectionPool.addAll(this.connectionPool); | |
LinkedList<Connection> removeFromPool = new LinkedList<>(); | |
List<Connection> connectionPoolTempCopy = new ArrayList<>(aliveConnectionPool); | |
for (Connection connection : connectionPoolTempCopy) { | |
if (!connection.healthcheck()) { | |
removeFromPool.add(connection); | |
} | |
} | |
this.uninitializedConnectionCount += removeFromPool.size(); | |
currentUninitializedConnectionCount = uninitializedConnectionCount; | |
aliveConnectionPool.removeAll(removeFromPool); | |
this.connectionPool.clear(); | |
this.connectionPool.addAll(aliveConnectionPool); | |
} | |
LinkedList<Connection> newConnectionPool = new LinkedList<>(); | |
if (currentUninitializedConnectionCount > 0) { | |
List<Connection> newConnections = this.createResource(currentUninitializedConnectionCount); | |
if (!newConnections.isEmpty()) { | |
newConnectionPool.addAll(newConnections); | |
} | |
} | |
synchronized (connectionPool) { | |
this.uninitializedConnectionCount -= newConnectionPool.size(); | |
this.connectionPool.addAll(newConnectionPool); | |
} | |
} catch (Exception ex) { | |
return false; | |
} | |
return true; | |
} | |
public Connection getConnection() throws Exception { | |
synchronized (resourceRetrievalLock) { | |
int tryCount = RESOURCE_RETRIEVAL_TRY_COUNT; | |
boolean isPoolEmpty = true; | |
synchronized (connectionPool) { | |
isPoolEmpty = connectionPool.isEmpty(); | |
} | |
while (tryCount > 0 && isPoolEmpty && createException == null) { | |
resourceRetrievalLock.wait(RESOURCE_RETRIEVAL_WAIT_PERIOD); | |
synchronized (connectionPool) { | |
isPoolEmpty = connectionPool.isEmpty(); | |
} | |
tryCount--; | |
} | |
synchronized (connectionPool) { | |
if (!connectionPool.isEmpty()) { | |
this.uninitializedConnectionCount++; | |
return connectionPool.poll(); | |
} else { | |
Exception resultException = null; | |
if(this.createException != null) { | |
resultException = this.createException; | |
} | |
if(resultException == null) { | |
resultException = new Exception("Connection pool is empty"); | |
} | |
throw resultException; | |
} | |
} | |
} | |
} | |
} | |
class Connection { | |
private String connectionParameter; | |
public Connection(String connectionParameter) { | |
this.connectionParameter = connectionParameter; | |
} | |
public boolean healthcheck() { | |
return true; | |
} | |
} | |
class ConnCreationResult { | |
private Connection connection; | |
private Exception exception; | |
public ConnCreationResult(Connection connection, Exception exception) { | |
this.connection = connection; | |
this.exception = exception; | |
} | |
public Connection getConnection() { | |
return connection; | |
} | |
public Exception getException() { | |
return exception; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment