miniconnectionpoolmanager代码注释

// Copyright 2007-2011 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms
// of any of the following licenses:
//
//  EPL, Eclipse Public License, http://www.eclipse.org/legal
//  LGPL, GNU Lesser General Public License, http://www.gnu.org/licenses/lgpl.html
//  MPL, Mozilla Public License 1.1, http://www.mozilla.org/MPL
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
package main.java.biz.source_code.miniConnectionPoolManager;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.LinkedList;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
/**
 * A lightweight standalone JDBC connection pool manager.
 * 一个轻量级、独立的jdbc连接池管理器
 * <p>
 * The public methods of this class are thread-safe.
 * 在这个类中的所有的共有方法都是现成安全的
 * <p>
 * Home page: <a * href="http://www.source-code.biz/miniconnectionpoolmanager">www.source-code.biz/miniconnectionpoolmanager</a>
 * <br>
 * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
 * Multi-licensed: EPL / LGPL / MPL.
 */
public class MiniConnectionPoolManager {
	/**PooledConnection对象的工厂*/
	private ConnectionPoolDataSource dataSource;
	
	/**连接池中的最大连接数*/
	private int maxConnections;
	
	/**超时时间设置*/
	private long timeoutMs;
	
	/**向文本输出流打印对象的格式化表示形式*/
	private PrintWriter logWriter;
	
	/**Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目*/
	private Semaphore semaphore;
	
	/**注册该对象便可获得由 PooledConnection 对象生成的事件的通知。*/
	private PoolConnectionEventListener poolConnectionEventListener;

	// The following variables must only be accessed within synchronized blocks. 同步块
	// @GuardedBy("this") could by used in the future.
	
	/**list of inactive PooledConnections 可用连接的集合*/
	private LinkedList<PooledConnection> recycledConnections; 
	
	/**number of active (open) connections of this pool 活动中的连接数目*/
	private int activeConnections;
	
	/** true if this connection pool has been disposed true时表示没有可用的连接*/
	private boolean isDisposed;
	
	// flag to purge the connection currently beeing closed instead of recycling it  标识当前被清除而不是被回收的链接 
	private boolean doPurgeConnection;
	
	// a PooledConnection which is currently within a PooledConnection.getConnection() call, or null
	// PooledConnection 对象表示到数据源的物理连接。该连接在应用程序使用完后可以回收而不用关闭,从而减少了需要建立连接的次数。 
	private PooledConnection connectionInTransition; 
	
	/**
	 * Thrown in {@link #getConnection()} or {@link #getValidConnection()} when
	 * no free connection becomes available within <code>timeout</code> seconds.
	 * 在指定时间内,没有可利用的链接的时候抛错
	 */
	/**超时异常*/
	public static class TimeoutException extends RuntimeException {
		private static final long serialVersionUID = 1;

		public TimeoutException() {
			super("Timeout while waiting for a free database connection.");
		}

		public TimeoutException(String msg) {
			super(msg);
		}
	}
	

	
	/**
	 * Constructs a MiniConnectionPoolManager object.
	 * 构建一个迷你连接池管理器对象
	 * @param dataSource 数据资源
	 *            the data source for the connections.
	 * @param maxConnections 连接数
	 *            the maximum number of connections.
	 * @param timeout  等待空闲链接的最长时间
	 *            the maximum time in seconds to wait for a free connection.
	 */
	public MiniConnectionPoolManager(ConnectionPoolDataSource dataSource,
			int maxConnections, int timeout) {
		//给相应的属性赋值
		this.dataSource = dataSource;
		this.maxConnections = maxConnections;
		//由秒装换成毫秒
		this.timeoutMs = timeout * 1000L;
		
		try {
			logWriter = dataSource.getLogWriter();
		} catch (SQLException e) {
			
		}
		//最大连接数小于一的时候抛出相应的异常
		if (maxConnections < 1) {
			throw new IllegalArgumentException("Invalid maxConnections value.");
		}
		//创建具有给定的许可数和给定的公平设置的 Semaphore
		//new Semaphore(初始的可用许可数目,争用时是否按照按先进先出的顺序);
		semaphore = new Semaphore(maxConnections, true);
		//创建相应的物理链接列表
		recycledConnections = new LinkedList<PooledConnection>();
		//创建监听器
		poolConnectionEventListener = new PoolConnectionEventListener();
	}
	  
	/**
	 * Constructs a MiniConnectionPoolManager object with a timeout of 60 seconds.
	 * 构建一个迷你连接池管理器对象在60秒的超时范围内
	 * @param dataSource 
	 *            the data source for the connections.
	 * @param maxConnections   
	 *            the maximum number of connections.
	 */
	public MiniConnectionPoolManager(ConnectionPoolDataSource dataSource,
			int maxConnections) {
		this(dataSource, maxConnections, 60);
	}

	/**
	 * Closes all unused pooled connections.
	 * 关闭连接池中的连接,即是将集合中的PooledConnection关闭
	 */
	public synchronized void dispose() throws SQLException {
		//没有可用的连接
		if (isDisposed) {
			return;
		}
		//反之,标识isDisposed=true
		isDisposed = true;
		//sql异常为null
		SQLException e = null;
		//将recycledConnectins中的链接统统关闭
		while (!recycledConnections.isEmpty()) {
			//从链表中移除
			PooledConnection pconn = recycledConnections.remove();
			try {
				//真正地关闭链接
				pconn.close();
			} catch (SQLException e2) {
				if (e == null) {
					e = e2;
				}
			}
		}
		if (e != null) {
			throw e;
		}
	}

	/**
	 * Retrieves a connection from the connection pool.
	 * 从连接池中检索(获取一个链接)
	 * <p>
	 * If <code>maxConnections</code> connections are already in use, the method
	 * waits until a connection becomes available or <code>timeout</code>
	 * seconds elapsed. When the application is finished using the connection,
	 * it must close it in order to return it to the pool.
	 * 
	 * 如果所有的链接都被占用,那么该方法会会在超时范围内等待可用的链接;
	 * 当应用程序完成对链接的使用,它必须将链接还回到连接池中去。
	 * @return a new <code>Connection</code> object.
	 * 		返回一个链接对象
	 * @throws TimeoutException
	 *             when no connection becomes available within
	 *             <code>timeout</code> seconds.
	 */
	/**获取链接*/
	public Connection getConnection() throws SQLException {
		return getConnection2(timeoutMs);
	}
	
	private Connection getConnection2(long timeoutMs) throws SQLException {
		// This routine is unsynchronized, because semaphore.tryAcquire() may block.
		//这个程序时异步的,因为semaphore.tryAcquire()可能引起阻塞
		synchronized (this) {
			//没有可用链接,抛出异常
			if (isDisposed) {
				throw new IllegalStateException("Connection pool has been disposed.");
			}
		}
		try {
			//当前信号量没有获得许可,抛出异常
			if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
				//如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
				throw new TimeoutException();
			}
		} catch (InterruptedException e) {
			throw new RuntimeException("Interrupted while waiting for a database connection.", e);
		}
		boolean ok = false;
		try {
			//获取链接
			Connection conn = getConnection3();
			ok = true;
			//返回链接
			return conn;
		} finally {
			//释放一个许可,将其返回给信号量。
			if (!ok) {
				semaphore.release();
			}
		}
	}

	private synchronized Connection getConnection3() throws SQLException {
		//没有可用的连接
		if (isDisposed) { // test again within synchronized lock
			throw new IllegalStateException("Connection pool has been disposed.");
		}
		//表示到数据源的物理连接
		PooledConnection pconn;
		//可用连接数不为空的时候,从中获取一个链接
		if (!recycledConnections.isEmpty()) {
			pconn = recycledConnections.remove();
		} else {
			//获取链接
			pconn = dataSource.getPooledConnection();
			//注册事件
			pconn.addConnectionEventListener(poolConnectionEventListener);
		}
		
		//与特定数据库的连接
		Connection conn;
		try {
			// The JDBC driver may call
			// ConnectionEventListener.connectionErrorOccurred()
			// from within PooledConnection.getConnection(). To detect this
			// within
			// disposeConnection(), we temporarily set connectionInTransition.
			connectionInTransition = pconn;
			conn = pconn.getConnection();
		} finally {
			connectionInTransition = null;
		}
		//活动的链接数+1
		activeConnections++;
		//状态判断
		assertInnerState();
		//返回特定数据库的链接
		return conn;
	}

	/**
	 * Retrieves a connection from the connection pool and ensures that it is valid by calling {@link Connection#isValid(int)}.
	 * 从数据库连接池中检索出一个链接并且保证被调用的是合法的
	 * <p>
	 * If a connection is not valid, the method tries to get another connection
	 * until one is valid (or a timeout occurs).
	 * 如果是不合法的,这个方法将试图获取另外的链接,知道合法
	 * <p>
	 * Pooled connections may become invalid when e.g. the database server is
	 * restarted.
	 * 链接可能是不合法的,当数据库服务器被重启
	 * <p>
	 * This method is slower than {@link #getConnection()} because the JDBC
	 * driver has to send an extra command to the database server to test the  connection.
	 * JDBC驱动需要发送额外的命令到数据库服务器,去检测连接
	 * <p>
	 * This method requires Java 1.6 or newer.
	 * 
	 * @throws TimeoutException
	 *             when no valid connection becomes available within
	 *             <code>timeout</code> seconds.
	 */
	public Connection getValidConnection() {
		//毫秒 当前时间
		long time = System.currentTimeMillis();
		//超时时间的设置
		long timeoutTime = time + timeoutMs;
		int triesWithoutDelay = getInactiveConnections() + 1;
		while (true) {
			Connection conn = getValidConnection2(time, timeoutTime);
			if (conn != null) {
				//成功获得连接则返回
				return conn;
			}
			triesWithoutDelay--;
			if (triesWithoutDelay <= 0) {
				triesWithoutDelay = 0;
				try {
					Thread.sleep(250);
				} catch (InterruptedException e) {
					throw new RuntimeException("Interrupted while waiting for a valid database connection.",e);
				}
			}
			//获取当前的时间
			time = System.currentTimeMillis();
			//判断是否已经超时,是则抛出异常
			if (time >= timeoutTime) {
				throw new TimeoutException("Timeout while waiting for a valid database connection.");
			}
		}
	}

	private Connection getValidConnection2(long time, long timeoutTime) {
		long rtime = Math.max(1, timeoutTime - time);
		Connection conn;
		try {
			conn = getConnection2(rtime);
		} catch (SQLException e) {
			return null;
		}
		rtime = timeoutTime - System.currentTimeMillis();
		int rtimeSecs = Math.max(1, (int) ((rtime + 999) / 1000));
		try {
			if (conn.isValid(rtimeSecs)) {
				return conn;
			}
		} catch (SQLException e) {
			
		}
		// This Exception should never occur. If it nevertheless occurs, it's
		// because of an error in the
		// JDBC driver which we ignore and assume that the connection is not
		// valid.
		// When isValid() returns false, the JDBC driver should have already
		// called connectionErrorOccurred()
		// and the PooledConnection has been removed from the pool, i.e. the
		// PooledConnection will
		// not be added to recycledConnections when Connection.close() is called.
		// But to be sure that this works even with a faulty JDBC driver, we
		// call purgeConnection().
		purgeConnection(conn);
		return null;
	}

	// Purges the PooledConnection associated with the passed Connection from the connection pool.
	/**关闭当前的连接*/
	private synchronized void purgeConnection(Connection conn) {
		try {
			doPurgeConnection = true;
			// (A potential problem of this program logic is that setting the
			// doPurgeConnection flag
			// has an effect only if the JDBC driver calls connectionClosed()
			// synchronously within
			// Connection.close().)
			conn.close();
		} catch (SQLException e) {
			
		}finally {
			// ignore exception from close()
			doPurgeConnection = false;
		}
	}
	/**回收连接*/
	private synchronized void recycleConnection(PooledConnection pconn) {
		if (isDisposed || doPurgeConnection) {
			disposeConnection(pconn);
			return;
		}
		if (activeConnections <= 0) {
			throw new AssertionError();
		}
		//活动的连接-1
		activeConnections--;
		//释放许可
		semaphore.release();
		//将连接添加到链表中
		recycledConnections.add(pconn);
		//判断
		assertInnerState();
	}
	
	/**断开连接*/
	private synchronized void disposeConnection(PooledConnection pconn) {
		//销毁连接
		pconn.removeConnectionEventListener(poolConnectionEventListener);
		if (!recycledConnections.remove(pconn)&& pconn != connectionInTransition) {
			// If the PooledConnection is not in the recycledConnections list   如果这个连接不在相应的链表中时
			// and is not currently within a PooledConnection.getConnection() call  也不是当前的连接时
			// we assume that the connection was active.            我们认为这个连接时活动的
			if (activeConnections <= 0) {
				throw new AssertionError();
			}
			//活动连接数-1
			activeConnections--;
			//释放许可
			semaphore.release();
		}
		//断开连接
		closeConnectionAndIgnoreException(pconn);
		//判断问题
		assertInnerState();
	}

	/**断开连接*/
	private void closeConnectionAndIgnoreException(PooledConnection pconn) {
		try {
			pconn.close();
		} catch (SQLException e) {
			log("Error while closing database connection: " + e.toString());
		}
	}
	/**日志输出*/
	private void log(String msg) {
		String s = "MiniConnectionPoolManager: " + msg;
		try {
			if (logWriter == null) {
				System.err.println(s);
			} else {
				logWriter.println(s);
			}
		} catch (Exception e) {
		}
	}
	/**用于判断连接池中的连接数问题*/
	private synchronized void assertInnerState() {
		if (activeConnections < 0) {
			throw new AssertionError();
		}
		if (activeConnections + recycledConnections.size() > maxConnections) {
			throw new AssertionError();
		}
		if (activeConnections + semaphore.availablePermits() > maxConnections) {
			throw new AssertionError();
		}
	}
	/**实现了ConnectionEventListener,注册该对象便可获得由 PooledConnection 对象生成的事件的通知*/
	private class PoolConnectionEventListener implements ConnectionEventListener {
		//实现其中两个方法
		
		/**当连接关闭的时候,会激活回收相应连接*/
		public void connectionClosed(ConnectionEvent event) {
			PooledConnection pconn = (PooledConnection) event.getSource();
			recycleConnection(pconn);
		}
		/**当连接发生错误时,断开当前的这个连接*/
		public void connectionErrorOccurred(ConnectionEvent event) {
			PooledConnection pconn = (PooledConnection) event.getSource();
			disposeConnection(pconn);
		}
	}

	/**
	 * Returns the number of active (open) connections of this pool.
	 * 返回连接池中处于激活状态的连接
	 * <p>
	 * This is the number of <code>Connection</code> objects that have been
	 * issued by {@link #getConnection()}, for which
	 * <code>Connection.close()</code> has not yet been called.
	 * 
	 * @return the number of active connections.
	 **/
	public synchronized int getActiveConnections() {
		return activeConnections;
	}

	/**
	 * Returns the number of inactive (unused) connections in this pool.
	 * 返回连接池中没有被激活的连接数目
	 * <p>
	 * This is the number of internally kept recycled connections, for which
	 * <code>Connection.close()</code> has been called and which have not yet
	 * been reused.
	 * 
	 * @return the number of inactive connections.
	 **/
	
	/**返回连接池中没有被激活的连接数目*/
	public synchronized int getInactiveConnections() {
		return recycledConnections.size();
	}

} // end class MiniConnectionPoolManager

针对代码相应的写了注释,相信也就容易看懂了!

但是我自己不理解的其实是那个synchronized这个!!有什么连接讲解的,介绍个资源看看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值