当前位置:   article > 正文

手写数据库连接池实战

手写数据库连接池实战
  • 释放连接,重回连接池,并且通知等待中的消费者

  • @param connection

*/

public void releaseConnection(Connection connection) {

if (connection != null) {

synchronized (pool) {

pool.addLast(connection);

// 通知消费者

pool.notifyAll();

}

}

}

/**

  • 直接获取连接,不知道超时时间,则会一直等待

  • @return

  • @throws InterruptedException

*/

public Connection connection() throws InterruptedException {

return connection(0);

}

/**

  • 指定获取连接时间

  • @param mills

  • @return

  • @throws InterruptedException

*/

public Connection connection(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(mills);

remaining = future - System.currentTimeMillis();

}

return pool.isEmpty() ? null : pool.removeFirst();

}

}

}

}

连接驱动模拟:

Connection是一个接口,我们通过动态代理来创建Connection,当执行Connection的commit方法时,通过 TimeUnit.MILLISECONDS.sleep(200);休眠线程来模拟执行事务提交。

package com.lizba.p3;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.sql.Connection;

import java.util.concurrent.TimeUnit;

/**

  •   数据库连接驱动动态代理模拟类
    
    • 1
  • @Author: Liziba

  • @Date: 2021/6/17 16:57

*/

public class ConnectionDriver {

private static final String COMMIT_OP = “commit”;

static class ConnectionHandler implements InvocationHandler {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// commit 时睡眠200ms

if (method.getName().equals(COMMIT_OP)) {

TimeUnit.MILLISECONDS.sleep(200);

}

return null;

}

}

public static final Connection createConnection() {

return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),

new Class<?>[] {Connection.class}, new ConnectionHandler());

}

}

客户端测试:

客户端使用多线程模拟对数据库发起多个连接,并通过统计获取和未获取的次数来计算在不同线程池大小和客户端连接数的情况下,客户端从线程池获取线程的成功和失败的次数。

package com.lizba.p3;

import java.sql.Connection;

import java.sql.SQLException;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.atomic.AtomicInteger;

/**

  •   连接池测试,使用CountdownLatch确保connectionThread能同时执行,并发获取连接
    
    • 1
  • @Author: Liziba

  • @Date: 2021/6/17 17:51

*/

public class PoolTest {

/** 初始化线程池 */

private static ConnectionPool pool = new ConnectionPool(10);

/** 保证所有线程都一起执行 */

private static CountDownLatch start = new CountDownLatch(1);

/** 保证main线程执行在所有线程执行完之后再往后执行 */

private static CountDownLatch end;

public static void main(String[] args) throws InterruptedException {

// 定义获取连接的线程数量

int threadSize = 10;

// 定义每个线程获取连接的次数

int count = 50;

end = new CountDownLatch(threadSize);

AtomicInteger getConnectionCount = new AtomicInteger();

AtomicInteger notGetConnectionCount = new AtomicInteger();

for (int i = 0; i < threadSize; i++) {

Thread t = new Thread(new Runner(count, getConnectionCount, notGetConnectionCount), “connectionThread”);

t.start();

}

start.countDown();

end.await();

System.out.println(“执行次数” + (threadSize * count));

System.out.println(“获取连接次数” + getConnectionCount);

System.out.println(“未获取连接次数” + notGetConnectionCount);

}

static class Runner implements Runnable {

private int count;

private AtomicInteger getConnectionCount;

private AtomicInteger notGetConnectionCount;

public Runner(int count, AtomicInteger getConnectionCount, AtomicInteger notGetConnectionCount) {

this.count = count;

this.getConnectionCount = getConnectionCount;

this.notGetConnectionCount = notGetConnectionCount;

}

@Override

public void run() {

try {

// 等待知道主线程执行完start.countDown();

start.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

// 循环获取连接

while (count > 0) {

try {

Connection connection = pool.connection(1000);

if (connection != null) {

try {

connection.createStatement();

connection.commit();

} finally {

// 释放连接

pool.releaseConnection(connection);

// 记录获取的数量

getConnectionCount.incrementAndGet();

}

} else {

// 记录未获取到的数量

notGetConnectionCount.incrementAndGet();

}

} catch (InterruptedException | SQLException e) {

e.printStackTrace();

} finally {

count–;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

image

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

tps://img2.imgtp.com/2024/03/13/H4lCoPEF.jpg" />

结尾

我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

[外链图片转存中…(img-WcHPyIJ0-1712416220757)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/869417
推荐阅读
相关标签
  

闽ICP备14008679号