Day4 多线程下对druid的测试

多线程下对druid的测试

今天继续Case2, 和之前的Case0相比呢,是继续比较多个线程池的性能对比。这次不同的是,用100个线程并发去执行25000个数据库的连接并释放。我们今天不研究他们不同线程池的性能对比,研究下这个测试用例用到的多线程,并发相关的东西,看懂这段代码。
在这里插入图片描述
可以看到下面的代码是druid连接池的测试方法,核心方式是p0

   public void test_0() throws Exception {
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setInitialSize(initialSize);
        dataSource.setMaxActive(maxActive);
        dataSource.setMinIdle(minPoolSize);
        dataSource.setMaxIdle(maxPoolSize);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(jdbcUrl);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestOnBorrow(testOnBorrow);

        for (int i = 0; i < executeCount; ++i) {
            p0(dataSource, "druid", threadCount);
        }
        System.out.println();
    }

AtomicLong & CountDownLatch

在p0中,看到定义了几个并发相关的类,原子类AtomicLong,并发工具类CountDownLatch,看到这两个熟悉又陌生的类差点给我送走,仔细回忆了下。

AtomicLong

AtomicLong是一个线程安全的计数器,不会受多线程的影响。

CountDownLatch

CountDownLatch是,初始一个数量这里面是100,每一次调用CountDown数量都会减1,
调用它的await方法,就会阻塞主线程,等待100归0后,才会继续执行。
如下面的代码中的startLatch,每个子线程的主方法体中,startLatch.await()就是在等待CountDown=0时,所有的子线程一起开始执行方法体的内容。

    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {

        final CountDownLatch startLatch = new CountDownLatch(1);
        final CountDownLatch endLatch = new CountDownLatch(threadCount);
        final AtomicLong blockedStat = new AtomicLong();
        final AtomicLong waitedStat = new AtomicLong();

        for (int i = 0; i < threadCount; ++i) {
            Thread thread = new Thread() {

                public void run() {
                    try {
                    //每个子线程在等待,统一开始
                        startLatch.await();

                        long threadId = Thread.currentThread().getId();

                        long startBlockedCount, startWaitedCount;
                        {
                            ThreadInfo threadInfo = ManagementFactory.getThreadMXBean().getThreadInfo(threadId);
                            startBlockedCount = threadInfo.getBlockedCount();
                            startWaitedCount = threadInfo.getWaitedCount();
                        }
                        for (int i = 0; i < LOOP_COUNT; ++i) {
                            Connection conn = dataSource.getConnection();
                            conn.close();
                        }

                        ThreadInfo threadInfo = ManagementFactory.getThreadMXBean().getThreadInfo(threadId);
                        long blockedCount = threadInfo.getBlockedCount() - startBlockedCount;
                        long waitedCount = threadInfo.getWaitedCount() - startWaitedCount;

                        blockedStat.addAndGet(blockedCount);
                        waitedStat.addAndGet(waitedCount);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                    //每个子线程执行完后,都会-1
                    endLatch.countDown();
                }
            };
            thread.start();
        }
        long startMillis = System.currentTimeMillis();
        long startYGC = TestUtil.getYoungGC();
        long startFullGC = TestUtil.getFullGC();
           //start归0后,所有的子线程开始跑。
        startLatch.countDown();
     //end开始等待。
        endLatch.await();
//等所有子线程跑完每个线程的25000个连接释放,就会回到主线程。继续往下走。
        long millis = System.currentTimeMillis() - startMillis;
        long ygc = TestUtil.getYoungGC() - startYGC;
        long fullGC = TestUtil.getFullGC() - startFullGC;

        System.out.println("thread " + threadCount + " " + name + " millis : "
                           + NumberFormat.getInstance().format(millis) + ", YGC " + ygc + " FGC " + fullGC
                           + " blockedCount " + blockedStat.get() + " waitedCount " + waitedStat.get());
    }

测试指标

blockedCount

这blockedCount是什么意思呢,我去看了下源码中的注释
(被阻止进入锁的次数) Number of times blocked to enter a lock

waitedCount

(等待锁的次数)Number of times waited on a lock

google翻译有点不太清楚。我理解就是blcokedCount是线程阻塞的次数总和。
waitedCount是等待获取锁的次数总和。这两个数值越少,代表数据库连接池的性能越高。

测试结果

可以明显发现druid的blcokedCount才是0或者1,性能非常高。
由于为了弄清楚blockedCount和waitedCount的含义,下次去复习下Thread的状态,和各个状态之间的转换。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
properties多数据源druid是指在使用Druid连接池的情况下,配置多个数据源的属性文件。Druid是一个高性能的开源连接池,支持多种数据库,并且具有强大的监控和统计功能。 在配置多数据源时,需要在属性文件中分别设置不同数据源的相关配置,包括数据库连接信息、连接池大小、最大等待时间等。以下是一个示例的多数据源Druid属性文件配置: ```properties # 数据源1 spring.datasource.druid.ds1.url=jdbc:mysql://localhost:3306/db1 spring.datasource.druid.ds1.username=root spring.datasource.druid.ds1.password=123456 spring.datasource.druid.ds1.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.ds1.initial-size=5 spring.datasource.druid.ds1.max-active=20 spring.datasource.druid.ds1.max-wait=60000 # 数据源2 spring.datasource.druid.ds2.url=jdbc:mysql://localhost:3306/db2 spring.datasource.druid.ds2.username=root spring.datasource.druid.ds2.password=123456 spring.datasource.druid.ds2.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.ds2.initial-size=5 spring.datasource.druid.ds2.max-active=20 spring.datasource.druid.ds2.max-wait=60000 ``` 在上述配置中,我们定义了两个数据源:ds1和ds2。每个数据源都有自己的连接信息和连接池配置。你可以根据实际需求配置更多的数据源。 注意,在使用多数据源时,你需要在代码中明确指定使用哪个数据源,可以通过注解或配置的方式来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值