1、连接池初始化:
public class ConnectionPool {
private LinkedList<Connection> pool = new LinkedList<Connection>();
// 初始化连接池
public ConnectionPool(int size) {
if (size > 0) {
for (int i = 0; i < size; i++) {
pool.addLast(ConnectionDriver.createConnection());
}
}
}
// 释放一个连接
public void realseConnection(Connection conn) {
synchronized (pool) {
pool.addLast(conn);// 用完的连接返回连接池
pool.notifyAll();// 连接池有新的数据通知所有等待的线程来获取新的连接
}
}
// 从连接池中获取一个连接
public Connection getConnection(int mills) throws InterruptedException {// 超时自动返回
synchronized (pool) {
if (mills <= 0) {
while (pool.size() <= 0) {
pool.wait();// 等待,直到获取到一个连接返回
}
return pool.removeFirst();
}
long curentMills = System.currentTimeMillis() + mills;
long remaining = mills;
while (pool.size() <= 0 && remaining > 0) {
pool.wait(remaining);// 超时直接返回null
remaining = curentMills - System.currentTimeMillis();// 连接数不足,并且超时未到,继续等待
}
if (pool.size() > 0) {
return pool.removeFirst();
}
return null;
}
}
}
2.模拟一个数据库驱动:
public class ConnectionDriver {
static class ConnectionHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("commit")) {
TimeUnit.MILLISECONDS.sleep(100);
}
return null;
}
}
public static final Connection createConnection() {
return (Connection) Proxy.newProxyInstance(ConnectionHandler.class.getClassLoader(),
new Class<?>[] { Connection.class }, new ConnectionHandler());
}
}
3.该连接池的使用方法,使用到了可以进行原子操作的AtomicInteger以及CountDownLatch工具类。
CountDownLatch介绍:
CountDownLatch 多个线程同时工作,然后其中几个可以随意并发执行, 但有一个线程需要等其他线程 ,工作结束后,才能开始。举个例子,开启多个线程分块下载一个大文件, 每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段, 那么这时候我们可以考虑使用CountDownLatch来控制并发。
CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。
public class ConnectionPoolTest {
public static ConnectionPool pool = new ConnectionPool(10);// 初始化线程池
public static CountDownLatch start = new CountDownLatch(1); // 所有线程同时执行任务
public static CountDownLatch end; // 子线程执行完成后主线程执行的标志
public static void main(String[] args) throws InterruptedException {
int count = 40;
int threadCount = 40;
end = new CountDownLatch(threadCount);
AtomicInteger got = new AtomicInteger();// 可以进行原子操作的Integer
AtomicInteger notGot = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
new Thread(new ConnectionRunner(count, got, notGot), "pool").start();
}
start.countDown(); // 计数器减1,计算器==0则阻塞完成
end.await();// 主线程等待所有子线程执行完成
System.out.println("total invoke : " + (threadCount * count));
System.out.println("got connection : " + got);
System.out.println("not got connection : " + notGot);
}
static class ConnectionRunner implements Runnable {
private int count;
private AtomicInteger got;
private AtomicInteger notGot;
/**
* @param count
* @param got
* @param notGot
*/
public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot) {
this.count = count;
this.got = got;
this.notGot = notGot;
}
@Override
public void run() {
try {
start.await(); // 子线程等待,直到所有子线程创建完成
}
catch (InterruptedException e) {
e.printStackTrace();
}
while (count > 0) {
try {
Connection conn = pool.getConnection(3000);
if (conn != null) {
try {
conn.createStatement();
conn.commit();
}
finally {
pool.realseConnection(conn);
got.incrementAndGet();// 原子加1操作
}
}
else {
notGot.incrementAndGet();
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
count--;
}
}
end.countDown();
}
}
}