packagecn.kgc.kb08.jdbc.dao3.impl;importcn.kgc.kb08.jdbc.dao3.SelRtn;importcn.kgc.kb08.jdbc.dao3.Dao;importcn.kgc.kb08.jdbc.dao3.Pool;importjava.lang.reflect.Method;import java.sql.*;import java.util.*;import java.util.concurrent.*;importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/*** 弹性连接池:生产和管理对象的*/
public final class ConPool implementsPool {//pool.maxIdel=30是什么 => 请看文档,官方会写//pool.retryInterval=50//pool.maxRetryCount=8
/*** 池中连接*/
classPoolCon {boolean free = true;booleancore;
Connection con;longidleBegin;public PoolCon(booleancore, Connection con) {this.core =core;this.con =con;
restIdle();
}public voidrestIdle() {if (!core) {this.idleBegin =System.currentTimeMillis();
}
}
}private ConcurrentMappool;private MapcnfPool;private MapcnfCon;/*** 执行定期清理线程池
* 检查核心连接对象的有效性,无效则创建新核心连接对象覆盖
* 检查临时连接对象是否超时,超时则关闭并移除*/
privateScheduledExecutorService schedule;privateExecutorService service;privateLock lock;privateCondition cond;private booleanclearing;publicConPool() {
initCnf();
initPool();
startClear();
}//塞进pool和mysql的配置:比如Map中driver:xxx的键值对
private voidinitCnf() {
cnfPool= PoolUtil.parse(Integer.class, "pool",
Arrays.asList(PoolConstant.POOL));
cnfCon= PoolUtil.parse(String.class, "mysql01",
Arrays.asList(PoolConstant.MYSQL));
}//初始化连接池
private voidinitPool() {final int MAX_COUNT =cnfPool.get(PoolConstant.POOL_MAX_COUNT);
service= Executors.newFixedThreadPool(MAX_COUNT * 2);
schedule=Executors.newSingleThreadScheduledExecutor();
lock= new ReentrantLock(true);
cond=lock.newCondition();//分段锁的集合
pool = new ConcurrentHashMap<>(MAX_COUNT);//池中连接
PoolCon pc;final int CORE_COUNT =cnfPool.get(PoolConstant.POOL_CORE_COUNT);for (Integer i = 0, j = 1; i <= CORE_COUNT; i++) {
pc= makePoolCon(true);if (null !=pc) {//给核心连接一个编号
pool.put(j++, pc);
}
}if (pool.size() == 0) {
System.err.println("连接池初始化失败,系统强制退出");
System.exit(-1);
}//如果配置让你失败便退出,且核心池数量小于一半
if (cnfPool.get(PoolConstant.POOL_EXIT_ON_ERR) == 1
&& pool.size() <= CORE_COUNT / 2) {
System.err.println("连接池初始化过半异常,系统强制退出");
System.exit(-1);
}
}/*** 创建一个池中的连接对象
*
*@paramcore 池对象类型,true:核心对象,false:临时对象
*@return
*/
private PoolCon makePoolCon(booleancore) {
PoolCon pc= null;//最大重试次数,创建n次,创建出一个连接对象
for (int i = 0; i <= cnfPool.get(PoolConstant.POOL_MAX_RETRY_COUNT); i++) {try{
Connection con=DriverManager.getConnection(
cnfCon.get(PoolConstant.MYSQL_URI),
cnfCon.get(PoolConstant.MYSQL_USER),
cnfCon.get(PoolConstant.MYSQL_PASS)
);
pc= newPoolCon(core, con);
}catch(SQLException e) {try{//创建失败就休息片刻再创建(重试)
TimeUnit.SECONDS.sleep(cnfPool.get(PoolConstant.POOL_RETRY_INTERVAL));continue;
}catch(InterruptedException e1) {
e1.printStackTrace();
System.out.println("cuocuocuo");
}
e.printStackTrace();
}
}returnpc;
}/*** 验证核心连接对象是否有效
*
*@parampc
*@return
*/
private booleanisPCValid(PoolCon pc) {try{
pc.con.createStatement().executeQuery("select 1");return true;
}catch(SQLException e) {return false;
}
}/*** 验证临时连接对象是否过期
*
*@parampc 池连接对象
*@returntrue:过期,false:没过期*/
private booleanisExpired(PoolCon pc) {return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - pc.idleBegin) >=cnfPool.get(PoolConstant.POOL_MAX_IDELE);
}/*** 验证用户是否超出配置最大时限
*@paramwaitBegin 计算参考起点时间
*@return
*/
private boolean isWaitExpired(longwaitBegin){return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()-waitBegin)>=cnfPool.get(PoolConstant.POOL_MAX_WAIT);
}/*** 开启定期清理任务
* maxIdle,最长闲置时间*/
private voidstartClear() {int delay =cnfPool.get(PoolConstant.POOL_MAX_IDELE);
schedule.scheduleWithFixedDelay(newRunnable() {
@Overridepublic voidrun() {
lock.lock();
clearing= true;for(Integer key : pool.keySet()) {
PoolCon pc=pool.get(key);if (!pc.free) {continue;
}if(pc.core) {if (!isPCValid(pc)) {
pool.put(key, makePoolCon(true));
}
}else{if (isExpired(pc) || !isPCValid(pc)) {
pool.remove(key);
}
}
}
clearing= false;
cond.signalAll();
lock.unlock();
}
}, delay, delay, TimeUnit.SECONDS);
}/*** 连接池销毁*/@Overridepublic voiddestory() {while (pool.size() > 0) {for(Integer key : pool.keySet()) {
PoolCon pc=pool.get(key);if(pc.free) {
pc.free= false;
PoolUtil.close(pc.con);
pool.remove(key);
}
}try{
TimeUnit.MILLISECONDS.sleep(cnfPool.get(PoolConstant.POOL_RETRY_INTERVAL));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}/***
*@return
*/
privatePoolCon fetch() {long waitBegin =System.currentTimeMillis();for (Integer i = 0; i <= cnfPool.get(PoolConstant.POOL_MAX_RETRY_COUNT); i++) {try{
lock.lock();if(clearing) {
cond.await();
}for(Integer key : pool.keySet()) {
PoolCon pc=pool.get(key);if (pc.free &&isPCValid(pc)) {
pc.free= false;returnpc;
}
}if(isWaitExpired(waitBegin)){return null;
}
TimeUnit.MILLISECONDS.sleep(cnfPool.get(PoolConstant.POOL_RETRY_INTERVAL));
}catch(Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}if(pool.size()
PoolCon pc= makePoolCon(false);if (null !=pc){
pc.free= false;
pool.put(pool.size()+1,pc);returnpc;
}
}return null;
}private voidgiveback(PoolCon pc){if(null==pc){return;
}if(!pc.core){
pc.restIdle();
}
pc.free= true;
}
@OverridepublicDao newDao(){return newDao() {private PreparedStatement getPst(Connection con, final String SQL, Object... params) throwsSQLException {
PreparedStatement pst=con.prepareStatement(SQL);if (null != params && params.length > 0) {for (int i = 0; i < params.length; i++) {
pst.setObject(i+ 1, params[i]);
}
}returnpst;
}private int update(PreparedStatement pst) throwsSQLException {returnpst.executeUpdate();
}private ResultSet query(PreparedStatement pst) throwsSQLException {returnpst.executeQuery();
}private MapparseMethod(Class c) {
Map mapMethod = new HashMap<>();final String PREFIX = "set";for(Method method : c.getDeclaredMethods()) {
String name=method.getName();if (!name.startsWith(PREFIX)) {continue;
}
name= name.substring(3);
name= name.substring(0, 1).toLowerCase() + name.substring(1);
mapMethod.put(name, method);
}returnmapMethod;
}private String[] parseStruct(ResultSetMetaData md) throwsSQLException {
String[] names= newString[md.getColumnCount()];for (int i = 0; i < names.length; i++) {
names[i]= md.getColumnLabel(i + 1);
}returnnames;
}
@Overridepublic int exeUpd(final String SQL, finalObject... params) {try{return service.submit(new Callable() {
@Overridepublic Integer call() throwsException {int rst = 0;
PoolCon pc= null;//Connection con = null;
PreparedStatement pst = null;try{
pc=fetch();if (null !=pc) {
pst=getPst(pc.con, SQL, params);
rst=update(pst);
}
}catch(SQLException e) {
rst= -1;
}finally{
PoolUtil.close(pst);
giveback(pc);
}returnrst;
}
}).get();
}catch(Exception e) {return -1;
}
}
@Overridepublic SelRtn exeSingle(final Class c, final String SQL, finalObject... params) {try{return service.submit(new Callable() {
@Overridepublic SelRtn call() throwsException {
PoolCon pc= null;
PreparedStatement pst= null;
ResultSet rst= null;try{
pc=fetch();
pst=getPst(pc.con, SQL, params);
rst=query(pst);if (null != rst &&rst.next()) {//调用类型(非Character基本类型包装类)c的,带有唯一字符串参数的构造方法//c.getConstructor(String.class)//基本类型创建对象
returnSelRtn.succeed(
c.getConstructor(String.class).newInstance(rst.getObject(1).toString()));
}else{return SelRtn.succeed(null);
}
}catch(Exception e) {
e.printStackTrace();
}finally{//close(rst, pst, con);
PoolUtil.close(rst, pst);
giveback(pc);
}returnSelRtn.fail();
}
}).get();
}catch(Exception e) {returnSelRtn.fail();
}
}
@Overridepublic SelRtn exeQuery(final Class c, final String SQL, finalObject... params) {try{return service.submit(new Callable() {
@Overridepublic SelRtn call() throwsException {
PoolCon pc= null;
PreparedStatement pst= null;
ResultSet rst= null;try{
pst=getPst(pc.con, SQL, params);
rst=query(pst);if (null != rst &&rst.next()) {
List list = new ArrayList<>();
Map map =parseMethod(c);
String[] names=parseStruct(rst.getMetaData());do{
T t=c.newInstance();for(String name : names) {
map.get(name).invoke(t, rst.getObject(name));
}
list.add(t);
}while(rst.next());returnSelRtn.succeed(list);
}else{return SelRtn.succeed(null);
}
}catch(Exception e) {
e.printStackTrace();
}finally{
PoolUtil.close(rst, pst);
giveback(pc);
}returnSelRtn.fail();
}
}).get();
}catch(Exception e) {returnSelRtn.fail();
}
}
};
}
}