【设计模式】单例模式

个人理解,单例模式就是创建一个独一无二的对象,在我们需要时才创建,如果用全局静态变量代替的话,就必须在程序一开始就创建,可能造成资源浪费。

单例模式确保一个类只有一个实例,并提供一个全局的访问点。

先来看看一个经典的单例模式代码:

 1 package cn.sp.singleton;
 2 /**
 3  * 单例模式  --  使用懒加载  -- 只适合单线程
 4  * @author 2YSP
 5  *
 6  */
 7 public class Singleton {
 8     
 9     private static Singleton singleton;
10     
11     private Singleton(){
12         
13     }
14     
15     public static Singleton getInstance(){//但是如果是多线程的话,会产生不同的实例,而不是一个独一无二的对象
16         if(singleton == null){
17             singleton = new Singleton();
18         }
19         
20         return singleton;
21     }
22 }

但是如果是多线程的话,会出问题。以下是改进后的代码。

 1 package cn.sp.singleton;
 2 /**
 3  * 单例模式  --  使用懒加载  -- 多线程版
 4  * @author 2YSP
 5  *
 6  */
 7 public class Singleton2 {
 8     
 9     private static Singleton2 singleton;
10     
11     private Singleton2(){
12         
13     }
14     
15     public synchronized static Singleton2 getInstance(){//使用同步,但是执行效率降低
16         if(singleton == null){
17             singleton = new Singleton2();
18         }
19         
20         return singleton;
21     }
22 }
package cn.sp.singleton;
/**
 * 单例模式  --  立即创建  -- 多线程版
 * @author 2YSP
 *
 */
public class Singleton3 {
    
    private static Singleton3 singleton = new Singleton3();
    
    private Singleton3(){
        
    }
    //如果应用程序总是创建并使用单件实例,或者在创建和运行方面的负担不太繁重,可使用此方法
    public  static Singleton3 getInstance(){
        
        return singleton;
    }
}
 1 package cn.sp.singleton;
 2 /**
 3  * 单例模式  --  加锁  -- 多线程版
 4  * @author 2YSP
 5  *
 6  */
 7 public class Singleton4 {
 8     
 9     private volatile static Singleton4 singleton ;//volatile 关键字保证变量的可见性
10     
11     private Singleton4(){
12         
13     }
14     //使用“双重检查加锁”,在getInstance()中减少使用同步,提示效率
15     public  static Singleton4 getInstance(){
16         if(singleton == null){
17             synchronized (Singleton4.class) {
18                 if(singleton == null){
19                     singleton = new Singleton4();
20                 }
21             }
22         }
23         return singleton;
24     }
25 }

 

 

推荐使用枚举实现单例模式,因为不光线程安全还不会因为序列化而产生新实例,防止反射攻击,具体可以查看这篇文章https://www.cnblogs.com/happy4java/p/11206105.html

 

原文地址:https://www.cnblogs.com/2YSP/p/6921309.html