--------------------------------------------------
目录
1.定义
2.常见的集中单例实现
a.饿汉式,线程安全 但效率比较低
b.单例模式的实现:饱汉式,非线程安全
c.饱汉式,线程安全简单实现
d.线程安全 并且效率高 单例模式最优方案
3.总结
a.使用枚举的单例模式
b.使用枚举,static处调用,初始化一次
--------------------------------------------------
1.定义
确保一个类只有一个实例,并提供一个全局访问点!
2.常见的集中单例实现
a.饿汉式,线程安全 但效率比较低
/** * 单例模式的实现:饿汉式,线程安全 但效率比较低 */ public class SingletonTest { // 定义一个私有的构造方法 private SingletonTest() { } // 将自身的实例对象设置为一个属性,并加上Static和final修饰符 private static final SingletonTest instance = new SingletonTest(); // 静态方法返回该类的实例 public static SingletonTest getInstancei() { return instance; } }
b.单例模式的实现:饱汉式,非线程安全
/** * 单例模式的实现:饱汉式,非线程安全 * */ 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; } }
c.饱汉式,线程安全简单实现
/** * 单例模式的实现:饱汉式,线程安全简单实现 * */ 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; } }
d.线程安全 并且效率高 单例模式最优方案
/** * 单例模式最优方案 * 线程安全 并且效率高 * */ 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; } }
3.总结
【以上单例模式】传统的两私有一公开(私有构造方法、私有静态实例(懒实例化/直接实例化)、公开的静态获取方法)涉及线程安全问题(即使有多重检查锁也可以通过反射破坏单例)
目前最为安全的实现单例的方法是通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。如下
a.使用枚举的单例模式
/** * 使用枚举的单例模式 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */ 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; } } }
b.使用枚举,static处调用,初始化一次
import java.util.ArrayList; import java.util.List; /** * 初始化的优雅实现 * 可以在static处调用, * 也可以在普通方法里调用,都保证只初始化一次 * * 当然将enum块的代码直接放到StaticInitTest类的private static 方法里做也是可以的 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */ public class StaticInitTest { private static List<Integer> dataList = null; static{ dataList = Singleton.INSTANCE.init(); } /** * * 单例模式来填充数据 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */ private static enum Singleton { INSTANCE; private List<Integer> list; private Singleton(){ fillData(); } /** * * 初始化数据 * * @see [相关类/方法](可选) * @since [产品/模块版本](可选) */ private void fillData(){ list = new ArrayList<Integer>(5); for(int i =1; i<6; i++){ list.add(i); } } /** * * 初始化的入口 * * @see [相关类/方法](可选) * @since [产品/模块版本](可选) */ public List<Integer> init(){ return list; } } }
参考资料:java单例之enum实现方式
时间: 2024-11-15 23:19:43