通俗地说,Java 中的 Singleton 类是允许一次通过单个实例访问它的类。这种设计模式用于限制类的不必要实例化,并确保每个 JVM 实例在任何时间点都只存在类的一个对象。因此,使用此模式,任何定义为 Singleton 的类都只有一个实例,并具有对其的全局访问点。与普通类不同,单例类不会在应用程序生命周期结束时销毁。
但是为什么我们首先需要一个单例类呢?
好吧,通过限制类的实例创建,它节省了内存空间,因为现在每次发出新请求时都不会创建对象。相反,将重复使用单个对象。这就是 Java 中的单例模式主要用于多线程和数据库应用程序的原因。它主要用于日志记录、缓存、线程池、配置设置等等。
我希望您清楚 Java 中单例类的概念。所以,现在让我们在这篇 Java 中的单例类文章中进一步了解它们是如何创建的。
为了在 Java 中创建类单例,您需要以下三样东西:
1.类的静态成员
1.私有构造函数
1.静态工厂方法
由于 Java 允许开发人员探索他们的视野,因此您可以通过多种方式设计 Singleton 类。下面我列出了最受欢迎的。
现在让我们一一深入研究这些方法中的每一种。
这是创建单例类的最简单方法,其中实例在类加载时创建。要使用此方法创建单例类,您需要按照以下步骤操作:
现在,让我们看看如何实现这些。
//Eager Initialization
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
如果您看到代码,您可以观察到每次我们实例化一个对象时,我们都在使用 getInstance() 方法而不是调用类构造函数。但它有其自身的缺点。如果您使用此方法创建类单例,则无论应用程序是否正在使用它,都会创建一个实例。
所以,让我们继续看另一种在 Java 中创建单例类的方法。
此方法称为延迟初始化,因为它将类实例的创建推迟到第一次使用。我的意思是,使用这种方法,只有在需要时才会创建对象。它有助于避免不必要地创建类实例。要以这种方式设计单例类,您需要遵循以下列出的步骤:
下面的代码显示了如何执行此操作。
//Lazy Initialization
public class LazySingleton {
private static LazySingleton INSTANCE = null;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (INSTANCE == null) {
synchronized(LazySingleton.class) {
INSTANCE = new LazySingleton();
}
}
return INSTANCE;
}
}
但是上述方法在并发场景中会引起一些担忧。由于单例模式主要用于多线程,并且如果多个线程同时进入 if 条件,则可能会引发问题。为了避免这种情况,我们尝试通过使全局访问方法同步来创建线程安全的单例类。这确保在任何时间点只有一个线程正在执行此方法。参考以下代码查看实现:
//Thread Safe Singleton
public class ThreadSafeSingleton {
private static ThreadSafeSingleton INSTANCE;
private ThreadSafeSingleton(){}
public static synchronized ThreadSafeSingleton getInstance(){
if(INSTANCE == null){
INSTANCE = new ThreadSafeSingleton();
}
return INSTANCE;
}
}
但有时这种方法也会变得非常麻烦,因为每次调用该方法时,它都需要等待锁被释放,然后该方法才能使用它。这会导致进程变慢,并导致我们采用下一种方法,即带双锁的延迟初始化。
在这种方法中,我们不同步方法。相反,我们将对象创建代码封装在一个同步块中。可以说,通过预先检查线程锁,它减少了获取锁的次数。这种方法通常会提高应用程序的性能。查看下面的代码,看看它是如何完成的。
//Lazy Initialization with Double Lock
public class LazyDoubleLockSingleton {
private static LazyDoubleLockSingleton INSTANCE = null;
private LazyDoubleLockSingleton() {}
public static LazyDoubleLockSingleton getInstance() {
if (INSTANCE == null) {
synchronized (LazyDoubleLockSingleton.class) {
if (INSTANCE == null) {
INSTANCE = new LazyDoubleLockSingleton();
}
}
}
return INSTANCE;
}
}
此方法基于 JSL(Java 语言规范),根据此 JVM 将仅在需要时加载静态数据成员。因此,当您的单例类加载到 JVM 中时,不会创建任何实例。此外,在程序执行期间,全局方法按顺序调用。使用此方法,您不必显式同步静态 getInstance() 以加载和初始化。静态类成员将以适当的顺序调用,全局方法的其余并发调用以相同的顺序返回,而无需执行同步开销。
下面是执行相同操作的代码。
//Lazy Load Method
public class LazyLoadSingleton {
private LazyLoadSingleton() {}
private static class SingletonClassHolder {
static final Var INSTANCE = new LazyLoadSingleton();
}
public static LazyLoadSingleton getInstance() {
return SingletonClassHolder.INSTANCE;
}
}
这种在 Java 中创建单例类的方法类似于 Eager 初始化方法。唯一的区别是此类的实例是在具有异常处理功能的静态块中创建的。
//Static Block Initialization
public class StaticBlockSingleton {
private static StaticBlockSingleton INSTANCE;
private StaticBlockSingleton(){}
//exception handling within static block
static{
try{
INSTANCE = new StaticBlockSingleton();
} catch (Exception e) {
throw new RuntimeException("Exception occured while creating a Singleton Class");
}
}
public static StaticBlockSingleton getInstance(){
return INSTANCE;
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.edureka.co/blog/singleton-class-in-java/
内容来源于网络,如有侵权,请联系作者删除!