面试必问! JUC 常用 4 大并发工具类是哪几个?( 四 )

iface) throws SQLException {return false;}}
连接池对象
package org.dance.day2.util.pool;import java.sql.Connection;import java.util.ArrayList;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedList;import java.util.concurrent.Semaphore;/*** 使用信号量控制数据库的链接和释放** @author ZYGisComputer*/public class DBPoolSemaphore {/*** 池容量*/private final static int POOL_SIZE = 10;/*** useful 代表可用连接* useless 代表已用连接*为什么要使用两个Semaphore呢?是因为,在连接池中不只有连接本身是资源,空位也是资源,也需要记录*/private final Semaphore useful, useless;/*** 连接池*/private final static LinkedList POOL = new LinkedList<>();/*** 使用静态块初始化池*/static {for (int i = 0; i < POOL_SIZE; i++) {POOL.addLast(SqlConnection.fetchConnection());}}public DBPoolSemaphore() {// 初始可用的许可证等于池容量useful = new Semaphore(POOL_SIZE);// 初始不可用的许可证容量为0useless = new Semaphore(0);}/*** 获取数据库连接** @return 连接对象*/public Connection takeConnection() throws InterruptedException {// 可用许可证减一useful.acquire();Connection connection;synchronized (POOL) {connection = POOL.removeFirst();}// 不可用许可证数量加一useless.release();return connection;}/*** 释放链接** @param 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();}}}
测试类:
package org.dance.day2.util.pool;import org.dance.tools.SleepTools;import java.sql.Connection;import java.util.Random;/*** 测试Semaphore* @author ZYGisComputer*/public class UseSemaphore {/*** 连接池*/public static final DBPoolSemaphore pool = new DBPoolSemaphore();private static class BusiThread extends Thread{@Overridepublic void run() {// 随机数工具类 为了让每个线程持有连接的时间不一样Random random = new Random();long start = System.currentTimeMillis();try {Connection connection = pool.takeConnection();System.out.println("Thread_"+Thread.currentThread().getId()+"_获取数据库连接耗时["+(System.currentTimeMillis()-start)+"]ms.");// 模拟使用连接查询数据SleepTools.ms(100+random.nextInt(100));System.out.println("查询数据完成归还连接");pool.returnConnection(connection);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {for (int i = 0; i < 50; i++) {BusiThread busiThread = new BusiThread();busiThread.start();}}}
测试返回结果:
Thread_11_获取数据库连接耗时[0]ms.Thread_12_获取数据库连接耗时[0]ms.Thread_13_获取数据库连接耗时[0]ms.Thread_14_获取数据库连接耗时[0]ms.Thread_15_获取数据库连接耗时[0]ms.Thread_16_获取数据库连接耗时[0]ms.Thread_17_获取数据库连接耗时[0]ms.Thread_18_获取数据库连接耗时[0]ms.Thread_19_获取数据库连接耗时[0]ms.Thread_20_获取数据库连接耗时[0]ms.查询数据完成归还连接当前有40个线程等待获取连接,,可用连接有0个Thread_21_获取数据库连接耗时[112]ms.查询数据完成归还连接...................查询数据完成归还连接当前有2个线程等待获取连接,,可用连接有0个Thread_59_获取数据库连接耗时[637]ms.查询数据完成归还连接当前有1个线程等待获取连接,,可用连接有0个Thread_60_获取数据库连接耗时[660]ms.查询数据完成归还连接当前有0个线程等待获取连接,,可用连接有0个查询数据完成归还连接...................当前有0个线程等待获取连接,,可用连接有8个查询数据完成归还连接当前有0个线程等待获取连接,,可用连接有9个