首页 > 其他 > 详细

单例模式

时间:2020-04-26 11:11:46      阅读:62      评论:0      收藏:0      [点我收藏+]

单例模式顾名思义也就是只有一个实例,并且它自己负责创建自己的对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

下面介绍下单例模式的几种实现方式:

1.懒汉式

懒汉式顾名思义就是这种实例化方式比较“懒”,只有在需要的时候才去创建实例对象。用的时候才去检查有没有实例,如果有则返回,没有则新建。有线程安全和线程不安全两种创建方式。

线程安全的方式:在多线程的条件下,可能导致创建的对象不唯一,存在线程安全的问题。

 1 public class Singleton {
 2     private static Singleton instance = null;
 3 
 4     private Singleton() {
 5     }
 6 
 7     //懒汉式
 8     public static Singleton getInstance() {
 9         if (instance == null) {
10             instance = new Singleton();
11         }
12         return instance;
13     }
14 
15 }

线程安全的方式:

 1 public class Singleton {
 2     private static Singleton instance = null;
 3 
 4     private Singleton() {
 5     }
 6 
 7     //懒汉式 线程安全
 8     public static synchronized Singleton getInstance() {
 9         if (instance == null) {
10             instance = new Singleton();
11         }
12         return instance;
13     }
14 
15 }

该方式能够保证线程安全,但是每次调用方法获取对象的时候,都加锁,执行效率低下。

2.饿汉式

从名字上也很好理解,就是“比较勤”,在类加载的时候就初始化了,不管你有没有用到,都先建好了再说。优点是实现简单,没有线程安全的问题,缺点是容易产生垃圾对象浪费内存空间。

 1 public class Singleton {
 2 
 3     private Singleton() {
 4     }
 5 
 6     private static Singleton instance2 = new Singleton();
 7 
 8     //饿汉式
 9     public static Singleton getInstance2() {
10         return instance2;
11     }
12 }

3.双重锁模式

该模式结合饿汉式和懒汉式的优点,在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还避免类加载的时候就创建对象节省了内存空间。

 1 public class Singleton {
 2 
 3     private Singleton() {
 4     }
 5 
 6     private static volatile Singleton instance = null;
 7 
 8     public static Singleton getInstance1() {
 9         if (instance == null) {
10             synchronized (Singleton.class) {
11                 if (instance == null) {
12                     instance = new Singleton();
13                 }
14             }
15         }
16         return instance;
17     }
18 }

4.静态内部类的方式

这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟饿汉式不同的是:饿汉式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。

 1 public class Singleton {
 2 
 3     private Singleton() {
 4     }
 5 
 6     public static Singleton getInstance() {
 7         return Inner.instance;
 8     }
 9 
10     public static class Inner {
11         private static final Singleton instance = new Singleton();
12     }
13 }

5.枚举方式

1 public enum Singleton {  
2     INSTANCE;  
3     public void whateverMethod() {  
4     }  
5 }

枚举的方式是比较少见的一种实现方式,但是看上面的代码实现,却更简洁清晰。并且她还自动支持序列化机制,绝对防止多次实例化。

上面就是单例模式的五种主要写法。我们来总结下,一般情况下,懒汉式(包含线程安全和线程不安全两种实现方式)都不推荐使用;饿汉式可以使用,可根据具体情况自主选择;在要明确实现 lazy loading 效果时,可以考虑静态内部类或者双重锁检验的实现方式;若涉及到反序列化创建对象时,大家也可以尝试使用枚举方式。

单例模式

原文:https://www.cnblogs.com/seedss/p/12777142.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!