线程的并发工具类 --- Semaphore

Semaphore(信号量)

是用来控制同时访问特定资源的线程数量,它通过协 调各个线程,以保证合理的使用公共资源。应用场景 Semaphore 可以用于做流 量控制,特别是公用资源有限的应用场景,比如数据库连接。假如有一个需求, 要读取几万个文件的数据,因为都是 IO 密集型任务,我们可以启动几十个线程 并发地读取,但是如果读到内存后,还需要存储到数据库中,而数据库的连接数 只有 10 个,这时我们必须控制只有 10 个线程同时获取数据库连接保存数据,否 则会报错无法获取数据库连接。这个时候,就可以使用 Semaphore 来做流量控制。

Semaphore 的构造方法 Semaphore(intpermits)接受一个整型的数字, 表示可用的许可证数量。Semaphore 的用法也很简单,首先线程使用 Semaphore的 acquire()方法获取一个许可证,使用完之后调用 release()方法归还许可证。还 可以用 tryAcquire()方法尝试获取许可证。


Semaphore 还提供一些其他方法,具体如下

•intavailablePermits():返回此信号量中当前可用的许可证数。 

•intgetQueueLength():返回正在等待获取许可证的线程数。 

•booleanhasQueuedThreads():是否有线程正在等待获取许可证。 

•voidreducePermits(intreduction):减少 reduction 个许可证,是个 protected 方法。 

•CollectiongetQueuedThreads():返回所有等待获取许可证的线程集合,是 个 protected 方法。


用Semaphore实现数据库连接池

/**
 *类说明:演示Semaphore用法,一个数据库连接池的实现
 */
public class DBPoolSemaphore {
	
	private final static int POOL_SIZE = 10;
	//两个指示器,分别表示池子还有可用连接和已用连接
	private final Semaphore useful,useless;
	//存放数据库连接的容器
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	//初始化池
	static {
        for (int i = 0; i < POOL_SIZE; i++) {
            pool.addLast(SqlConnectImpl.fetchConnection());
        }
	}
	public DBPoolSemaphore() {
		this.useful = new Semaphore(10);
		this.useless = new Semaphore(0);
	}
	
	/*归还连接*/
	public void returnConnect(Connection connection) throws InterruptedException {
		if(connection!=null) {
			System.out.println("当前有"+useful.getQueueLength()+"个线程等待数据库连接!!"
					+"可用连接数:"+useful.availablePermits());
			useless.acquire();
			synchronized (pool) {
				pool.addLast(connection);
			}
			useful.release();
		}
	}
	
	/*从池子拿连接*/
	public Connection takeConnect() throws InterruptedException {
		useful.acquire();
		Connection connection;
		synchronized (pool) {
			connection = pool.removeFirst();
		}
		useless.release();
		return connection;
	}
	
}
发布了18 篇原创文章 · 获赞 4 · 访问量 152

猜你喜欢

转载自blog.csdn.net/weixin_42081445/article/details/104907681
今日推荐