【问题标题】:Handling connection pool exhaustion and avoiding deadlock in Hibernate/C3P0在 Hibernate/C3P0 中处理连接池耗尽并避免死锁
【发布时间】:2017-03-26 11:59:07
【问题描述】:

我的旧应用程序遵循链来查询我的数据库:Spring Tx -> Hibernate -> C3P0。现在我需要在现有架构的基础上实现新功能。

我通常通过使用@Transactional 注释或手动调用PlatformTransactionManager 来输入事务上下文。

有时,为了执行异步和大数据操作,我使用SessionFactory API 打开一个无状态会话。我们的线程池控制得很好,我们从来没有遇到任何额外的问题

第一次,我的要求是并行执行多个数据库操作以加快性能。我对此表示怀疑,因为我对多线程操作非常小心。

对于数据库中的每个实体,我可以在单独的线程上执行协调操作。但是每个协调操作对它产生的两个线程中的每一个都使用一对连接。所以基本上每个线程有4个连接。

多线程课教导学生为了防止死锁(吃哲学家问题),资源应该以事务的方式获取:一旦你获得了一个fork,如果你不能在合理的时间内获得第二个,释放第一个然后再试一次。

我的问题很简单。鉴于SessionFactory API,如果池已满,我如何编写不会无限期等待来自 c3p0 的 4 个连接的代码?我的意思是我需要 4 个StatelessSessions,只有在有 4 个空间的情况下,否则我可以等待并重试。

据我所知,SessionFactory API 处于阻塞状态,不允许设置看门狗

【问题讨论】:

    标签: java multithreading hibernate dining-philosopher


    【解决方案1】:

    目前的想法是使用普通的旧解决方法。

    一般来说,在 Java 世界中,如果 API 不提供用于获取资源的看门狗方法,您可以将其委托给 Future,后者提供 get(int timeout, TimeUnit timeUnit) API 来限制执行。

    第一步:资源获取的看门狗定时器

    所以基本上,我如何在超时范围内获得无状态会话?

    private Future<StatelessSession> getStatelessSession(SessionFactory sessionFactory)
    {
        return asyncTaskExecutor.submit(new Callable<StatelessSession>()
        {
    
            @Override
            public StatelessSession call() throws Exception
            {
                return sessionFactory.openStatelessSession();
            }
        });
    }
    
    try {
        StatelessSession session = getStatelessSession(sessionFactory).get(3000,TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // go to step 2
    }
    

    第 2 步:按照哲学家的方式吃饭

    正如我所说,我的问题看起来基本上像用餐哲学家,只是我们不仅要拿两个叉子,还有勺子和刀子,总共要拿 4 个。

    StatelessSession session1, session2, session3, session4;
    for (int i=0; i<MAX_ATTEMPTS;i++) {
        try {
            session1 = tryGetSessionOrBoooooom();
        } catch(TimeoutException ex) {
            continue;
        }
        try {
            session2 = tryGetSessionOrBoooooom();
        } catch(TimeoutException ex) {
            session1.close();
            continue;
        }
        try {
            session3 = tryGetSessionOrBoooooom();
        } catch(TimeoutException ex) {
            session2.close();
            session1.close();
            continue;
        }
        try {
            session4 = tryGetSessionOrBoooooom();
        } catch(TimeoutException ex) {
            session3.close();
            session2.close();
            session1.close();
            continue;
        }
    }
    

    如果您超出 MAX_ATTEMPTS 会发生什么,这取决于您,开发者!

    【讨论】:

      猜你喜欢
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 2022-08-09
      • 1970-01-01
      • 2017-07-10
      • 1970-01-01
      相关资源
      最近更新 更多