java - 在 Lazy Load Getter 上同步

标签 java lazy-loading synchronized

由于我没有发现任何涉及该主题的问题,我想我应该分享我对以下场景的解决方案。答案可能很明显,但我走了很长的路才找到答案。 :) 我非常感谢对问题和答案以及其他解决方案的反馈。

场景:

假设您有一个多线程程序,并且需要数据库连接(或其他一些共享对象)来实现程序中的某些功能,而程序的其他部分根本不需要它。但是应该只有一个到数据库的连接。

同时,您想检测数据库连接丢失并尝试即时重新连接。

为了解决这个问题,您实现了一个延迟加载模式“getter”,它还在返回连接对象之前检查连接有效性。

您的代码可能如下所示:

public class Main {
  private DB _db;

  public static void main(String[] args) {
    new Main().start();
  }

  private void start() {
    // Program code goes here
    // You create several threads, some of which may call getDB() whenever they need DB access
  }

  public DB getDB() {
    if (_db == null) {
      _db = getDBConnection();
    } else if (!_db.isConnectionValid()) {
      /*
       * DB connection is not valid anymore. Let's close it and
       * try to get a new connection.
       */
      _db.close();
      _db = getDBConnection();
    }

    return _db;
  }

  private DB getDBConnection() {
    DB db;

    // Obtain a new connection...
    ...

    return db;
  }
}

问题:

多个线程可能几乎同时尝试获取数据库连接。当某些类保持对它们的引用时,甚至有可能多个连接共存。

最佳答案

Several threads may try to obtain a db connection at nearly the same time. It is even possible that several connects co-exist when some classes keep references to them.

在这种情况下,您需要一个池,因为您可以获得多个不同的实例。有许多可用的数据库连接池,一些 JDBC 驱动程序有自己的。我建议你使用JDBC驱动自带的或者使用C3P0之类的作为数据库连接池。

更具体地说,您需要以其他线程无法获得相同连接的方式建立连接(而不仅仅是获取它)。一个简单的例子是使用队列。

private final Queue<DB> freeDBs = new ConcurrentLinkedQueue<>();

public DB acquireDB() {
    DB db = freeDBs.poll();
    if (db != null && db.isConnectionValid()) 
        return db;
    if (db != null)
        db.close();
    return getDBConnection();
}

public void release(DB db) {
    if (freeDBs.size() >= MAX_FREE_SIZE)
        db.close();
    else
        freeDBs.add(db);
}

关于java - 在 Lazy Load Getter 上同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11899395/

相关文章:

Angular 2 loadChildren 不与 canActivateChild 一起工作

c# - .Net 单例属性的延迟初始化

java - jstack线程转储是否一致?

java - 使用 Selenium 的多浏览器环境中的 GUI

java - Python 相当于 Java 的 Set.add()?

Java ZipInputStream 在读取图像的 ZipEntry 后关闭

java - Android:Activity 到 Activity,第二个 Activity 无法调用 setContentView?

java - 在 Hibernate 中对属性使用惰性

java - 解锁锁定同步块(synchronized block)的可靠方法

java - 对同一类中方法的无参数调用产生 NullPointerException