在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使用其他机制来实现静态同步方法?如果我必须在类中实现多个静态同步方法,那么最佳实践是什么?
谢谢大家!
亲切的问候!
答案 0 :(得分: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
是一个坏主意”(如this one),有很多讨论,我认为在课堂上进行同步也是如此。
答案 1 :(得分:3)
您可以通过多种方式创建单身人士。
一种推荐的方法是使用枚举(保证只创建一个实例):
public enum ConnectionFactory {
INSTANCE;
}
或者您可以在加载类时静态创建它:
public class ConnectionFactory {
private static ConnectionFactory INSTANCE = new ConnectionFactory();
private ConnectionFactory() {}
public static ConnectionFactory getInstance() {
return INSTANCE;
}
}
如果你需要懒洋洋地加载它,你可以使用这个习语(而不是double checked locking anti-pattern)
public class ConnectionFactory {
private static class ConnectionFactoryHolder {
private static ConnectionFactory INSTANCE = new ConnectionFactory();
}
public static ConnectionFactory getInstance() {
return ConnectionFactoryHolder.INSTANCE;
}
}
答案 2 :(得分:2)
是的,静态方法在其类对象上同步。我不担心这里的表现,因为这可能不是你的表演热点。做到这一点很简单,随时随地进行优化。
答案 3 :(得分:2)
静态同步方法使用类上的锁。对于您的示例,它将访问ConnectionFactory类对象上的锁。最佳做法是不要长时间保持锁定。是否有多个同步方法本身并不是问题。
答案 4 :(得分:0)
Effective Java 建议使用Enums创建单例。所以你的代码看起来像这样:
public enum ConnectionFactory{
INSTANCE;
// Other factory methods go here.
}
}