1.使用HashMap和lock机制 缺点是,在大量的加锁解锁过程中消耗性能 https://blog.csdn.net/shengxiaohua1/article/details/120702347
private Map<String, Connection> connectionPool = new HashMap<String, Connection>();
private ReentrantLock lock = new ReentrantLock();
public Connection getConnection(String key) {
try {
lock.lock();
if (connectionPool.containsKey(key)) {
return connectionPool.get(key);
} else {
Connection conn = createConnection();
connectionPool.put(key, conn);
return conn;
}
} finally {
lock.unlock();
}
}
private Connection createConnection() {
return null;
}
上面的代码中HashMap可以替换成ConcurrentHashMap,这样可以不使用lock。但是这样又无法保证创建连接的原子性。产生了下面的方案:
2.使用ConcurrentHashMap和FutureTask作为线程池 ConcurrentHashMap和FutureTask都是线程安全的,故代码里没有额外加锁
private ConcurrentHashMap<String, FutureTask> connectionPool = new ConcurrentHashMap<String, FutureTask>();
public Connection getConnection(String key) throws Exception {
FutureTask<Connection> connectionTask = connectionPool.get(key);
if (connectionTask != null) {
return connectionTask.get();
} else {
Callable<Connection> callable = new Callable<Connection>() {
@Override
public Connection call() throws Exception {
return createConnection();
}
};
FutureTask<Connection> newTask = new FutureTask<Connection>(callable);
connectionTask = connectionPool.putIfAbsent(key, newTask);
if (connectionTask == null) {
connectionTask = newTask;
connectionTask.run();
}
return connectionTask.get();
}
}
private Connection createConnection() {
return null;
}
3.LinkedList + Semaphore
public class DBPoolSemaphore {
private final static int POOL_SIZE = 10;
private final Semaphore useful, useless;
private final static LinkedList<Connection> POOL = new LinkedList<>();
static {
for (int i = 0; i < POOL_SIZE; i++) {
POOL.addLast(SqlConnection.fetchConnection());
}
}
public DBPoolSemaphore() {
useful = new Semaphore(POOL_SIZE);
useless = new Semaphore(0);
}
public Connection takeConnection() throws InterruptedException {
useful.acquire();
Connection connection;
synchronized (POOL) {
connection = POOL.removeFirst();
}
useless.release();
return connection;
}
public void returnConnection(Connection connection) throws InterruptedException {
if(null!=connection){
System.out.println("当前有"+useful.getQueueLength()+"个线程等待获取连接,,"
+"可用连接有"+useful.availablePermits()+"个");
useless.acquire();
synchronized (POOL){
POOL.addLast(connection);
}
useful.release();
}
}
}
4.java并发编程艺术208页 LinkedList + synchronized + Object.wait/Object.notify
public class ConnectionPool {
private LinkedList<Connection> pool = new LinkedList<Connection>();
public ConnectionPool(int initialSize) {
if (initialSize > 0) {
for (int i = 0; i < initialSize; i++) {
pool.addLast(ConnectionDriver.createConnection());
}
}
}
public void releaseConnection(Connection connection) {
if (connection != null) {
synchronized (pool) {
pool.addLast(connection);
pool.notifyAll();
}
}
}
public Connection fetchConnection(long mills) throws InterruptedException {
synchronized (pool) {
if (mills <= 0) {
while (pool.isEmpty()) {
pool.wait();
}
return pool.removeFirst();
} else {
long future = System.currentTimeMillis() + mills;
long remaining = mills;
while (pool.isEmpty() && remaining > 0) {
pool.wait(remaining);
remaining = future - System.currentTimeMillis();
}
Connection result = null;
if (!pool.isEmpty()) {
result = pool.removeFirst();
}
return result;
}
}
}
}
总结 1、线程池需要一个保存所有线程的容器,可以选择HashMap,可以选择LinkedList等。 2、获取线程的时候由于存在竞争,所以需要枷锁lock或synchronized。 3、还需要监控池子中的容量,使用semaphore计数阻塞或Object.wait或LockSupport.park,总之当容量没有剩余的时候需要阻塞。
|