一对一免费咨询: 18215660330

单例模式是最简单的设计模式之一。有时我们只需要一个类的实例,例如由多个对象共享的单个数据库连接,因为为每个对象创建单独的数据库连接可能成本很高。同样,应用程序中可以有一个配置管理器或错误管理器来处理所有问题,而不是创建多个管理器。

定义:
单例模式是一种设计模式,它将类的实例化限制为一个对象。
让我们看看实现这样一个类的各种设计选项。如果你对静态类变量和访问修饰符有很好的处理,这应该不是一项艰巨的任务。

方法1:经典实施

filter_none
编辑
play_arrow

brightness_4
// Classical Java implementation of singleton
// design pattern
class Singleton
{
private static Singleton obj;

// private constructor to force use of
// getInstance() to create Singleton object
private Singleton() {}

public static Singleton getInstance()
{
if (obj==null)
obj = new Singleton();
return obj;
}
}

这里我们声明了getInstance()静态,以便我们可以在不实例化类的情况下调用它。第一次调用getInstance()时,它会创建一个新的单例对象,之后它只返回相同的对象。请注意,在我们需要它并调用getInstance()方法之前,不会创建Singleton obj。这称为惰性实例化。

上述方法的主要问题是它不是线程安全的。请考虑以下执行顺序。

独生子

此执行序列为单例创建两个对象。因此,这种经典的实现不是线程安全的。

方法2:使getInstance()同步

filter_none
编辑
play_arrow

brightness_4
// Thread Synchronized Java implementation of
// singleton design pattern
class Singleton
{
private static Singleton obj;

private Singleton() {}

// Only one thread can execute this at a time
public static synchronized Singleton getInstance()
{
if (obj==null)
obj = new Singleton();
return obj;
}
}
这里使用synchronized确保一次只有一个线程可以执行getInstance()。
这种方法的主要缺点是,在创建单例对象时每次使用synchronized都很昂贵,并且可能会降低程序的性能。但是,如果getInstance()的性能对于您的应用程序并不重要,则此方法提供了一种简洁明了的解决方案。

方法3:急切实例化

filter_none
编辑
play_arrow

brightness_4
// Static initializer based Java implementation of
// singleton design pattern
class Singleton
{
private static Singleton obj = new Singleton();

private Singleton() {}

public static Singleton getInstance()
{
return obj;
}
}
这里我们在静态初始化器中创建了singleton实例。当加载类时,JVM执行静态初始化程序,因此保证它是线程安全的。仅当单例类很轻并且在整个程序执行期间使用时才使用此方法。

方法4(最佳):使用“ 双重检查锁定 ”
如果在创建对象后仔细注意,则同步不再有用,因为现在obj不会为空,并且任何操作序列都将导致一致的结果。
因此,当obj为null时,我们只会获取一次getInstance()的锁定。这样我们只会同步第一条路,正是我们想要的。

filter_none
编辑
play_arrow

brightness_4
// Double Checked Locking based Java implementation of
// singleton design pattern
class Singleton
{
private volatile static Singleton obj;

private Singleton() {}

public static Singleton getInstance()
{
if (obj == null)
{
// To make thread safe
synchronized (Singleton.class)
{
// check again as multiple threads
// can reach above step
if (obj==null)
obj = new Singleton();
}
}
return obj;
}
}
我们已经声明了obj volatile,它确保多个线程在初始化为Singleton实例时正确提供obj变量。这种方法大大减少了每次调用synchronized方法的开销。

成都软件开发 最好的成都软件定制开发公司
18215660330