下面是两种实现单例的方法。各有什么优点和缺点?
静态初始化:
class Singleton {
private Singleton instance;
static {
instance = new Singleton();
}
public Singleton getInstance() {
return instance;
}
}
延迟初始化是:
class Singleton {
private Singleton instance;
public Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}
}
同步访问器
public class Singleton {
private static Singleton instance;
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重检查锁定和易失性
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
Singleton localInstance = instance;
if (localInstance == null) {
synchronized (Singleton.class) {
localInstance = instance;
if (localInstance == null) {
instance = localInstance = new Singleton();
}
}
}
return localInstance;
}
}
按需持有者习语
public class Singleton {
public static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
第一个是热切初始化。 急切的初始化甚至在使用实例之前就创建实例,这不是最佳实践。
第二个是延迟初始化。 惰性实现在单线程环境中工作得很好,但是当涉及到多线程系统时,如果多个线程同时位于 if 循环内,则可能会导致问题。它将破坏单例模式,并且两个线程将获得单例类的不同实例。
注意:静态块只能直接访问静态块外部定义的静态变量。您想要限制为仅创建一个实例的对象应该是static。第一个方法在编译期间失败,第二个方法要求您首先创建对象
遵循以下方法:
class Singleton
{
private static Singleton instance;
private Singleton()
{
}
public static Singleton getInstance()
{
if(instance == null)
instance = new Singleton();
return instance;
}
}
确保在其他地方没有创建对象,因此将构造函数更改为 private
让你的班级像这样
public class Singleton {
private Singleton() {
}
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
并称其为..
Singleton instance = Singleton.getInstance();
静态初始化器不能抛出异常并将 RuntimeException 吸收到 ClassDefNotFoundException 中,这不会停止执行。所以你可以看到很多 ClassDefNotFoundException 出现在您的日志中,您甚至可能直到很久以后才意识到出现了问题,因为执行仍在继续。
第二种方法允许RuntimeExceptions停止执行。
更多详情请点击这里: https://twasink.net/2006/07/07/how-not-to-handle-exceptions-from-static-code-block-in-java/
如果您需要在应用程序启动时初始化一些东西,请使用静态块。 f.ex,人们可能想从某个文件中加载一些有用的属性......等等
static {
instance = new Singleton();
loadStuff();
}
使用延迟初始化
class Singleton {
private Singleton instance;
public Singleton getInstance(){
if (instance == null) instance = new Singleton();
loadStuff()
return instance;
}
}
并且 loadStuff 仅在首次调用
Singleton.getInstance()
时才会被触发。