文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何在Java项目中模拟一个数据库连接池

2023-06-06 13:34

关注

本文章向大家介绍如何在Java项目中模拟一个数据库连接池,主要包括如何在Java项目中模拟一个数据库连接池的使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Java的特点有哪些

Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。2.Java具有简单性、面向对象、分布式、安全性、平台独立与可移植性、动态性等特点。3.使用Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。

由于 java.sql.Connection 只是一个接口,最终实现是由数据库驱动提供方来实现,考虑到本例只是演示,我们通过动态代理构造一个 Connection,该 Connection 的代理仅仅是在调用 commit() 方法时休眠 100 毫秒

public class ConnectionDriver {  static class ConnectionHandler implements InvocationHandler {    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      if ("commit".equals(method.getName())) {        TimeUnit.MICROSECONDS.sleep(100);      }      return null;    }  }    public static Connection createConnection() {    return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),        new Class<?>[]{Connection.class}, new ConnectionHandler());  }}

接下来是线程池的实现。本例通过一个双向队列来维护连接,调用方需要先调用 fetchConnection(long) 方法来指定在多少毫秒内超时获取连接,当连接使用完成后,需要调用 releaseConnection(Connection) 方法将连接放回线程池

public class ConnectionPool {  private final LinkedList<Connection> pool = new LinkedList<>();  public ConnectionPool(int initialSize) {    // 初始化连接的最大上限    if (initialSize > 0) {      for (int i = 0; i < initialSize; i++) {        pool.addLast(ConnectionDriver.createConnection());      }    }  }  public void releaseConnection(Connection connection) {    if (connection != null) {      synchronized (pool) {                pool.addLast(connection);        pool.notifyAll();      }    }  }    public Connection fetchConnection(long mills) throws InterruptedException {    synchronized (pool) {      // 完全超时      if (mills < 0) {        while (pool.isEmpty()) {          pool.wait();        }        return pool.removeFirst();      } else {        long future = System.currentTimeMillis() + mills;        long remaining = mills;        while (pool.isEmpty() && remaining > 0) {          pool.wait(remaining);          remaining = future - System.currentTimeMillis();        }        Connection result = null;        if (!pool.isEmpty()) {          result = pool.removeFirst();        }        return result;      }    }  }}

最后编写一个用于模拟客户端获取连接的示例,该示例将模拟多个线程同时从连接池获取连接,并记录总尝试获取数、获取成功数和获取失败数

public class ConnectionPoolTest {  static ConnectionPool pool = new ConnectionPool(10);  static CountDownLatch start = new CountDownLatch(1);  static CountDownLatch end;  public static void main(String[] args) throws InterruptedException {    // 线程数量    int threadCount = 200;    end = new CountDownLatch(threadCount);    int count = 20;    AtomicInteger got = new AtomicInteger();    AtomicInteger notGot = new AtomicInteger();    for (int i = 0; i < threadCount; i++) {      Thread thread = new Thread(new ConnectionRunner(count, got, notGot), "ConnectionRunnerThread");      thread.start();    }    start.countDown();    end.await();    System.out.println("total invoke : " + (threadCount * count));    System.out.println("got connection : " + got);    System.out.println("not got connection : " + notGot);  }  static class ConnectionRunner implements Runnable {    int count;    AtomicInteger got;    AtomicInteger notGot;    public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot) {      this.count = count;      this.got = got;      this.notGot = notGot;    }    @Override    public void run() {      try {        start.await();      } catch (Exception e) {        e.printStackTrace();      }      while (count > 0) {        try {          // 从线程池中获取连接,如果 1000ms 内无法获取到,将返回 null          // 分别统计获取连接的数量 got 和未获取到的数量 notGot          Connection connection = pool.fetchConnection(1000);          if (connection != null) {            try {              connection.createStatement();              connection.commit();            } finally {              pool.releaseConnection(connection);              got.incrementAndGet();            }          } else {            notGot.incrementAndGet();          }        } catch (Exception e) {          e.printStackTrace();        } finally {          count--;        }      }      end.countDown();    }  }}

笔者设置线程数量为 200 时,得出结果如下

如何在Java项目中模拟一个数据库连接池

当设置为 500 时,得出结果如下,当然具体结果根据机器性能而异

如何在Java项目中模拟一个数据库连接池

可见,随着客户端线程数的增加,客户端出现超时无法获取连接的比率不断升高。这种等待超时模式能保证程序出问题时,线程不会一直运行,而是按时返回,并告知客户端获取连接出现问题。数据库连接池的实际也可以应用到其他资源获取的场景,针对昂贵资源的获取都应该加以限制

到此这篇关于如何在Java项目中模拟一个数据库连接池的文章就介绍到这了,更多相关的内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯