連接池小實例
工作之餘看了一下Java的等待通知機制原理,然后里面有一個資料庫連接池的小Demo,覺得蠻有意思。所以看完之後,自己動手寫了一個簡單的實例,程式碼雖然簡單,但是對於理解連接池還是小有幫助。話不多說,直接上程式碼。
鏈接佔位:後面有時間了再來總結Java的等待通知機制
連接定義
public class Connection {
public void execute() {
try {
Thread.sleep((long) (Math.random() * 10));
} catch (InterruptedException e) {
}
}
}
連接驅動定義
public class ConnectionDriver {
public static Connection createConnection() {
return new Connection();
}
}
連接池定義
public class ConnectionPool {
private final LinkedList<Connection> pool = new LinkedList<>();
public ConnectionPool(int count) {
if (count <= 0) {
count = 1;
}
for (int i = 0;i < count;i++) {
pool.addLast(ConnectionDriver.createConnection());
}
}
public Connection fetchConnection() throws InterruptedException {
return fetchConnection(-1);
}
public Connection fetchConnection(int mil) throws InterruptedException {
synchronized (pool) {
if (mil <= 0) {
while (pool.isEmpty()) {
pool.wait();
}
return pool.removeFirst();
} else {
long fuTime = System.currentTimeMillis() + mil;
long remain = mil;
while (pool.isEmpty() && remain > 0) {
pool.wait(remain);
remain = fuTime - System.currentTimeMillis();
}
Connection result = null;
if (!pool.isEmpty()) {
result = pool.removeFirst();
}
return result;
}
}
}
public void releaseConnection(Connection connection) {
if (connection == null) {
return;
}
synchronized (pool) {
pool.addLast(connection);
pool.notifyAll();
}
}
}
連接池測試
public class ConnectionPollCeshi {
public static void main(String[] args) throws InterruptedException {
int threadCount = 10;
ConnectionPool pool = new ConnectionPool(5);
CyclicBarrier start = new CyclicBarrier(1);
CountDownLatch end = new CountDownLatch(threadCount);
AtomicInteger gotSuccess = new AtomicInteger();
AtomicInteger gotFailed = new AtomicInteger();
for (int i = 0;i < threadCount;i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
start.await();
} catch (Exception e) { }
for (int i = 0;i < 10;i++) {
try {
Connection connection = pool.fetchConnection(2);
if (connection == null) {
gotFailed.incrementAndGet();
} else {
connection.execute();
pool.releaseConnection(connection);
gotSuccess.incrementAndGet();
}
} catch (InterruptedException e) {
gotFailed.incrementAndGet();
}
}
end.countDown();
}
}).start();
}
end.await();
System.out.println("獲取成功: " + gotSuccess.get());
System.out.println("獲取失敗: " + gotFailed.get());
}
}
運行結果
獲取成功: 48
獲取失敗: 5
實現原理
上面使用了經典的等待通知機制,分為等待角色和通知角色,如下:
等待角色偽程式碼
{
while(條件不變) {
obj.wait();
}
}
通知角色偽程式碼
{
改變條件
obj.notifyAll();
}
對於Java等待通知裡面的等待隊列、同步隊列還有很多值得梳理的地方,後面有時間後來認真總結,今天划水就先划到這裡。