Java单例设计模式的理解与常规实现方式
2023-04-13 16:34:28
1:Java单例模式是一种常见的设计模式,具有以下特点:
单例类只能有一个例子。
一个例子必须创建自己唯一的例子。 这个例子必须提供给所有其他对象。
单例模式确保一个类别只有一个例子,并将这个例子实例化并提供给整个系统。
2:java中单例模式的写法也有很多种,我在这里列举几种常用的方法:
1、饿汉式,线程安全 但效率相对较低:/** * 实现单例模式:饿汉式,线程安全 但效率相对较低 */ public class SingletonTest { // 定义私有结构方法 private SingletonTest() { } // 将自己的实例对象设置为属性,加上static和final修饰符 private static final SingletonTest instance = new SingletonTest(); // 静态方法返回此类实例 public static SingletonTest getInstancei() { return instance; } }
2、懒汉风格,非线程安全: /** * 实现单例模式:懒汉风格,非线程安全 * */ public class SingletonTest { // 定义私有结构方法(防止通过 new SingletonTest()去实例化) private SingletonTest() { } // 定义Singletontest类型的变量(不初始化,注意不要在这里使用final关键词。 private static SingletonTest instance; // 定义静态方法(调用时将Singletontest初始化,但多线程访问时,可能导致重复初始化问题) public static SingletonTest getInstance() { if (instance == null) instance = new SingletonTest(); return instance; } }
3、懒汉风格,线程安全简单 : /** * 实现单例模式:懒汉风格,简单实现线程安全 * */ public class SingletonTest { // 定义私有结构方法(防止通过 new SingletonTest()去实例化) private SingletonTest() { } // 定义Singletontest类型的变量(不初始化,注意不要在这里使用final关键词。 private static SingletonTest instance; // 定义静态方法(调用时将Singletontest初始化,使用synchronized 避免多线程访问,可能会导致重复初始化问题) public static synchronized SingletonTest getInstance() { if (instance == null) instance = new SingletonTest(); return instance; } }
4、线程安全 并且效率高 单例模式的最佳方案 /** * 单例模式的最佳方案 * 线程安全 并且效率高 * */ public class SingletonTest { // 定义一种私有结构方法 private SingletonTest() { } //定义静态私有变量(不初始化,不使用final关键字,使用volatile保证了instance变量在多线程访问中的可见性,避免了instance初始化时其他变量属性没有赋值,被另外线程调用) private static volatile SingletonTest instance; //定义共同的静态方法,返回这种类型的例子 public static SingletonTest getIstance() { // 实例化时是否判断对象(不使用同步代码块,instance不等于null,直接返回对象,提高运行效率) if (instance == null) { //同步代码块(当对象未初始化时,使用同步代码块,以确保对象在第一次创建多线程访问时,不再重复创建) synchronized (SingletonTest.class) { ///未初始化,初始instance变量 if (instance == null) { instance = new SingletonTest(); } } } return instance; } }
5、静态内部模式 /** * 静态内部模式 * */ public class Singleton { private static class SingletonTest { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonTest.INSTANCE; } }
例如,在设计模式下,即使有多个检查锁,也可以通过反射破坏单例
6、目前,实现单例最安全的方法是通过内部静态enum实现,因为JVM将确保enum不能反射,结构方法只执行一次,如下: /** * 使用枚举单例模式 * * @author uu */ public class EnumSingleton{ private EnumSingleton(){} public static EnumSingleton getInstance(){ return Singleton.INSTANCE.getInstance(); } private static enum Singleton{ INSTANCE; private EnumSingleton singleton; ///JVM会保证这种方法绝对只调用一次 private Singleton(){ singleton = new EnumSingleton(); } public EnumSingleton getInstance(){ return singleton; } } public static void main(String[] args) { EnumSingleton obj0 = EnumSingleton.getInstance(); EnumSingleton obj1 = EnumSingleton.getInstance(); //输出结果:obj0=obj1true System.out.println(obj0=obj1true System.out.println(obj0=obj1 + (obj0=obj1); } }
我想谈谈我的个人理解,希望能对你有所帮助。