8

我在 Java 中实现单例模式时提出了这个问题。尽管下面列出的示例不是我的真实代码,但与原始代码非常相似。

public class ConnectionFactory{
    private static ConnectionFactory instance;

    public static synchronized ConnectionFactory getInstance(){
        if( instance == null ){
            instance = new ConnectionFactory();
        }

        return instance;
    }

    private ConnectionFactory(){
        // private constructor implementation
    }
}

因为我不太确定静态同步方法的行为,所以我从谷歌得到了一些建议——在同一个类中不要(或尽可能少)多个静态同步方法。我猜在实现静态同步方法时,使用了属于 Class 对象的锁,因此多个静态同步方法可能会降低系统性能。

我对吗?还是JVM使用其他机制来实现静态同步方法?如果我必须在一个类中实现多个静态同步方法,最佳实践是什么?

谢谢你们!

亲切的问候!

4

5 回答 5

7

最好的方法(尽可能少地更改代码)是这样做:

public class ConnectionFactory{
    private static ConnectionFactory instance = new ConnectionFactory();

    public static ConnectionFactory getInstance(){
        return instance;
    }

    private ConnectionFactory(){
    }
}

如您所见,现在getInstance方法中没有真正的需要,因此您可以将代码简化为:

public class ConnectionFactory{
    public static final ConnectionFactory INSTANCE = new ConnectionFactory();

    private ConnectionFactory(){
    }
}

关于同步的 UPD:最好的方法是在外部类不可见的锁上同步,即:

public class ConnectionFactory{
    private static final Object lock = new Object();

    public static void doSmth() {
        synchronized (lock) {

           ...
        }
    }

    public static void doSmthElse() {
        synchronized (lock) {

           ...
        }
    }
}

有很多关于“为什么同步this是一个坏主意”的讨论(比如这个),我认为在课堂上同步也是如此。

于 2010-06-02T13:22:07.733 回答
3

有几种方法可以创建单例。

一种推荐的方法是使用枚举(保证只创建一个实例):

public enum ConnectionFactory {

  INSTANCE;

}

或者您可以在类加载时静态创建它:

public class ConnectionFactory {

  private static ConnectionFactory INSTANCE = new ConnectionFactory();

  private ConnectionFactory() {}

  public static ConnectionFactory getInstance() {
    return INSTANCE;
  }    

}

如果你需要延迟加载它,你可以使用这个成语(而不是双重检查锁定反模式

public class ConnectionFactory {

  private static class ConnectionFactoryHolder {
    private static ConnectionFactory INSTANCE = new ConnectionFactory();
  }

  public static ConnectionFactory getInstance() {
    return ConnectionFactoryHolder.INSTANCE;
  }

}
于 2010-06-02T13:27:01.340 回答
2

是的,静态方法在其类对象上同步。我不会担心这里的性能,因为这可能不是您的性能热点。做简单,优化您需要的时间和地点。

于 2010-06-02T13:22:09.467 回答
2

静态同步方法使用类上的锁。在您的示例中,它将访问 ConnectionFactory 类对象上的锁。最佳做法是不要持有超过你必须的时间。是否有多个同步方法本身不是问题。

于 2010-06-02T13:22:24.003 回答
0

Effective Java推荐使用 Enums 来创建单例。所以你的代码看起来像这样:

public enum ConnectionFactory{
INSTANCE;

// Other factory methods go here.

}

}

于 2010-07-01T19:49:59.270 回答