【java】数据库连接池的自定义实现

    xiaoxiao2025-07-22  7

    数据库连接池的使用

    传统方式 当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。这一点自己在平时写程序的时候都是自己创建connection对象,然后用完就关闭。这就很耗时和浪费资源

    创建连接和关闭连接的过程也是比较消耗时间的,当多线程并发的时候,系统就会变得很卡顿。

    同时,一个数据库同时支持的连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光,后续线程发起的数据库连接就会失败。

    改进方式: 与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。 如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建. 使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。 倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。 整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。

    还记得上安卓课时候,张吴波老师说连接池就像一个鱼缸一样,要吃鱼的时候就拿出一条来,吃完了就放回去,把我们都逗笑了。。。。23333

    代码

    自定义数据库连接池的实现代码:就是借用操作系统中的生产者-消费者模型,来维护一个缓冲区。这次进行并发控制。

    package dbpool; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.LinkedList; /** * describe: * * @author yanzhizheng * @date 2019//26 * 按照how2j上实现的线程池 */ public class ConnectPool { private LinkedList<Connection> pool = new LinkedList<Connection>(); int size; public ConnectPool(int size) { this.size = size; init(); //调用init方法初始化队列 } public void init(){ //加载驱动源 try { Class.forName("com.mysql.jdbc.Driver"); for (int i = 0; i < size; i++) { Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root","mysql"); pool.addLast(conn); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { } } public synchronized Connection getConnection(){ while (pool.isEmpty()) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } return pool.removeFirst(); } public synchronized void releaseConnction(Connection conn) { pool.addLast(conn); this.notifyAll(); //唤醒等待的进程 } public static void main(String[] args) { ConnectPool pool = new ConnectPool(3); //初始化10个连接对象放到池子中 for (int i = 0; i < 10; i++) { new WorkThread("work thread" + i, pool).start(); } } } class WorkThread extends Thread { private ConnectPool pool; public WorkThread(String name, ConnectPool pool) { super(name); this.pool = pool; } public void run() { Connection c = pool.getConnection();//获取连接池中的连接 System.out.println(this.getName() + ":\t 获取连接" + "连接的对象的值" + c.toString()); try(Statement psmt = c.createStatement()) { Thread.sleep(10000); //睡眠10ms容易有效果 //执行sql语句 } catch (SQLException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } pool.releaseConnction(c); } }

    代码结果

    可以看到后面的线程都是使用那三个连接对象。

    最新回复(0)