Semaphore是一種在多線程環境下使用的設施,該設施負責協調各個線程,以保證它們能夠正確、合理的使用公共資源的設施,
也是操作系統中用於控制進程同步互斥的量。Semaphore是一種計數信號量,用於管理一組資源,內部是基於AQS的共享模式。
它相當於給線程規定一個量從而控制允許活動的線程數。
利用Semaphore設計一個鏈接池。
package com.business.thread.Semaphore;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
//數據庫連接的平庸實現
public class SqlConnectionImpl implements Connection{
//重寫Connection的方法,此處省略
//拿一個數據庫連接
public static final Connection fetchConnection() {
// TODO Auto-generated method stub
return new SqlConnectionImpl();
}
}
package com.business.thread.Semaphore;
//一個使用Semaphore實現的數據庫連接池
import java.sql.Connection;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
/*Semaphore是一種在多線程環境下使用的設施,該設施負責協調各個線程,以保證它們能夠正確、合理的使用公共資源的設施,
也是操作系統中用於控制進程同步互斥的量。Semaphore是一種計數信號量,用於管理一組資源,內部是基於AQS的共享模式。
它相當於給線程規定一個量從而控制允許活動的線程數。*/
public class DBPoolSemaphore {
//連接池的大小爲10
private final static int POOL_SIZE = 10;
//存放連接的容器
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//分別表示可用連接和已用連接
private final Semaphore useFul,useLess;
//初始化線程池
static {
for(int i=0;i<POOL_SIZE;i++) {
pool.addLast(SqlConnectionImpl.fetchConnection());
}
}
/*
* Semaphore主要構造方法
* Semaphore(int permits):構造方法,創建具有給定許可數的計數信號量並設置爲非公平信號量。
* Semaphore(int permits,booleanfair):構造方法,當fair等於true時,創建具有給定許可數的計數信號量並設置爲公平信號量。 void
* acquire():從此信號量獲取一個許可前線程將一直阻塞。相當於一輛車佔了一個車位。 void acquire(int
* n):從此信號量獲取給定數目許可,在提供這些許可前一直將線程阻塞。比如n=2,就相當於一輛車佔了兩個車位。 void
* release():釋放一個許可,將其返回給信號量。就如同車開走返回一個車位。 void release(int n):釋放n個許可。
* int availablePermits():當前可用的許可數。
*/
public DBPoolSemaphore(){
this.useFul = new Semaphore(POOL_SIZE);
this.useLess = new Semaphore(0);
}
//歸還連接
public void returnConnection(Connection connection) throws InterruptedException {
if(connection!=null) {
System.out.println("當前有"+useFul.getQueueLength()+"個線程等待數據庫連接!"+
"可用連接數: "+useFul.availablePermits());
useLess.acquire();
//對這個池進行加鎖
synchronized (pool) {
pool.add(connection);
}
useFul.release();
}
}
//從池子拿連接
public Connection takeConnection() throws InterruptedException {
useFul.acquire();
Connection connection;
synchronized (pool) {
connection = pool.removeFirst();
}
useLess.release();
return connection;
}
}
package com.business.thread.Semaphore;
import java.sql.Connection;
import java.util.Random;
//測試數據庫連接池
public class AppTest {
private static DBPoolSemaphore dbPool = new DBPoolSemaphore();
//拿數據庫連接的線程
private static class busiThread extends Thread{
public void run() {
Random r = new Random();//讓每個線程有個鏈接時間不一樣
long start = System.currentTimeMillis();
Connection connection;
try {
connection = dbPool.takeConnection();
System.out.println("Thread_"+Thread.currentThread().getId()+
"_獲取數據庫連接共耗時【"+(System.currentTimeMillis()-start)+"】ms");
Thread.sleep(100+r.nextInt(100));
System.out.println("查詢數據完成,歸還連接");
dbPool.returnConnection(connection);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for(int i = 0;i<50;i++) {
Thread thread = new busiThread();
thread.start();
}
}
}