Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 正在尝试使用多个线程仅创建一个数据库连接_Java_Multithreading_Synchronized_Locks - Fatal编程技术网

Java 正在尝试使用多个线程仅创建一个数据库连接

Java 正在尝试使用多个线程仅创建一个数据库连接,java,multithreading,synchronized,locks,Java,Multithreading,Synchronized,Locks,上面的代码首先尝试获取数据库连接的实例。如果不能这样做,它将进入一个同步方法,该方法将再次检查,如果仍然没有实例,它将创建一个新实例 我之所以有两个方法来检查这一点,是因为第一个方法没有同步,很多线程可以同时运行它,但我不希望线程同时运行实际创建新连接的方法 我的问题是,一旦线程到达instanceNotFoundDoubleCheckSynced方法,它们都会等待运行它的机会 有人能建议我如何避开这件事吗?我认为在生产环境中这不会是一个问题,因为在建立数据库连接之前,不太可能有这么多的调用会出

上面的代码首先尝试获取数据库连接的实例。如果不能这样做,它将进入一个同步方法,该方法将再次检查,如果仍然没有实例,它将创建一个新实例

我之所以有两个方法来检查这一点,是因为第一个方法没有同步,很多线程可以同时运行它,但我不希望线程同时运行实际创建新连接的方法

我的问题是,一旦线程到达instanceNotFoundDoubleCheckSynced方法,它们都会等待运行它的机会

有人能建议我如何避开这件事吗?我认为在生产环境中这不会是一个问题,因为在建立数据库连接之前,不太可能有这么多的调用会出现在这个方法中,但是在我的JUnits中,有10000个线程被触发,它们都被卡住了


谢谢

您应该避免双重检查锁定,因为这样做很容易出错。我认为如果您使用,您只需在一个内部类中直接实例化共享对象,这会更好。它将更简单、更高效。

我认为问题在于,您正在测试一个不现实的场景,其中所有线程都会启动并尝试获得连接。由于a获得连接需要时间b,因此有许多线程同时启动,它们都设法通过第一次非同步检查,并开始等待同步调用。我建议将测试线程的数量设置为实际的100-200,并在启动线程时添加一个随机延迟

此外,您还可以将双重检查简化为单个方法,并添加适当的错误处理:

public static Database getInstance()
{
    if( instance == null )
    {
        return instanceNotFoundDoubleCheckSynced();
    }
    return instance;
}


synchronized private static Database instanceNotFoundDoubleCheckSynced()
{
    if( instance == null )
    {
        Connection connection = establishConnection();
        if( connection != null )
        {
            instance = new Database( connection );
        }

    }
希望这有帮助


斯拉瓦·伊梅舍夫(Slava Imeshev)

现在单身汉的练习越来越糟糕。我不建议为您的项目实施单例解决方案。如果您要继续进行此设计的话。一个建议是让代码在启动时运行。如果它恰好是web应用程序,您可以通过创建一个侦听器来实现。还要考虑一下当远程服务器重新启动时会发生什么情况。由于这是单例,您是否必须重新启动jvm?
class MyClass {

   public static Database getInstance()
   {
       if( instance == null )
       {
           synchronized (MyClass.class) 
           {
             if( instance == null )
             {
                 Connection connection = establishConnection();
                 if( connection == null )
                 {
                     throw new RuntimeException("Cannot establish connection");
                 }
             }

             instance = new Database( connection );
          } 
       }

      return instance;
   }
}