如何在java中同步静态方法
在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使用其他机制来实现静态同步方法? 如果我必须在类中实现多个静态同步方法,那么最佳实践是什么?
谢谢你们!
亲切的问候!
最好的方法(尽可能减少代码中的更改)是这样做的:
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
是一个坏主意”(就像这个一样),我认为在课堂上同步也是如此。
有几种方法可以创建单例。
一种推荐的方法是使用枚举(保证只创建一个实例):
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; } }
是的,静态方法在其类对象上同步。 我不担心这里的表现,因为这可能不是你的表演热点。 做到简单,优化您需要的时间和地点。
静态同步方法使用类上的锁。 在您的示例中,它将访问ConnectionFactory类对象上的锁。 最佳做法是不要长时间保持锁定。 您是否拥有多个同步方法本身并不是问题。
Effective Java建议使用Enums创建单例。 所以你的代码看起来像这样:
public enum ConnectionFactory{ INSTANCE; // Other factory methods go here. }
}