java 单例模式5种写法

学习整理安全

饱汉模式(懒汉模式)并发

 1 // 饱汉
 2 // UnThreadSafe
 3 public class Singleton1 {
 4   private static Singleton1 singleton = null;
 5   private Singleton1() {
 6   }
 7   public static Singleton1 getInstance() {
 8     if (singleton == null) {
 9       singleton = new Singleton1();
10     }
11     return singleton;
12   }
13 }

优势:懒加载启动快,资源占用小,使用时才实例化,无锁。app

缺点:非线程安全。函数

 

饱汉模式(懒汉模式)--线程安全性能

 1 public class Singleton {
 2 
 3     /**
 4      * 定义一个变量来存储建立好的类实例
 5      */
 6 
 7     private static Singleton uniqueInstance = null;
 8 
 9     /**
10      * 私有化构造方法,好在内部控制建立实例的数目
11      */
12 
13     private Singleton(){
14     }
15 
16     /**
17      * 定义一个方法来为客户端提供类实例
18      * @return 一个Singleton的实例
19      */
20 
21     public static synchronized Singleton getInstance(){
22 
23         //判断存储实例的变量是否有值
24         if(uniqueInstance == null){
25             //若是没有,就建立一个类实例,并把值赋值给存储类实例的变量
26             uniqueInstance = new Singleton();
27         }
28 
29         //若是有值,那就直接使用
30         return uniqueInstance;
31     }
32 
33     /**
34      * 示意方法,单例能够有本身的操做
35      */
36 
37     public void singletonOperation(){
38 
39 //功能处理
40 
41     }
42 
43     /**
44      * 示意属性,单例能够有本身的属性
45      */
46 
47     private String singletonData;
48 
49     /**
50      * 示意方法,让外部经过这些方法来访问属性的值
51      * @return 属性的值
52      */
53 
54     public String getSingletonData(){
55 
56         return singletonData;
57 
58     }
59 
60 }            

 优势:同上,但加锁了。学习

 缺点:synchronized 为独占排他锁,并发性能差。即便在建立成功之后,获取实例仍然是串行化操做。spa

 

饱汉模式(懒汉模式)--双重加锁检查DCL(Double Check Lock)线程

 1 public class Singleton {
 2 
 3     /**
 4      * 对保存实例的变量添加volatile的修饰
 5      */
 6 
 7     private volatile static Singleton instance = null;
 8 
 9     private Singleton(){
10 
11     }
12 
13     public static Singleton getInstance(){
14 
15 //先检查实例是否存在,若是不存在才进入下面的同步块
16 
17         if(instance == null){
18 
19 //同步块,线程安全的建立实例
20 
21             synchronized(Singleton.class){
22 
23 //再次检查实例是否存在,若是不存在才真的建立实例
24 
25                 if(instance == null){
26 
27                     instance = new Singleton();
28 
29                 }
30 
31             }
32 
33         }
34 
35         return instance;
36 
37     }
38 
39 }

 优势:懒加载,线程安全。code

 注:实例必须有 volatile 关键字修饰,其保证初始化彻底。blog

 

饿汉模式

 1 public class Singleton {
 2 
 3 //4:定义一个静态变量来存储建立好的类实例
 4 
 5 //直接在这里建立类实例,只会建立一次
 6 
 7     private static Singleton instance = new Singleton();
 8 
 9 //1:私有化构造方法,好在内部控制建立实例的数目
10 
11     private Singleton(){
12 
13     }
14 
15 //2:定义一个方法来为客户端提供类实例
16 
17 //3:这个方法须要定义成类方法,也就是要加static
18 
19 //这个方法里面就不须要控制代码了
20 
21     public static Singleton getInstance(){
22 
23 //5:直接使用已经建立好的实例
24 
25         return instance;
26 
27     }
28 
29 }

 优势:饿汉模式天生是线程安全的,使用时没有延迟。

 缺点:启动时即建立实例,启动慢,有可能形成资源浪费。

 

Holder模式

 1 public class Singleton {
 2     /**
 3      * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
 4      * 没有绑定关系,并且只有被调用到才会装载,从而实现了延迟加载
 5      */
 6     private static class SingletonHolder{
 7         /**
 8          * 静态初始化器,由JVM来保证线程安全
 9          */
10         private static Singleton instance = new Singleton();
11     }
12     /**
13      * 私有化构造方法
14      */
15     private Singleton(){
16     }
17     public static  Singleton getInstance(){
18         return SingletonHolder.instance;
19     }
20 }

 优势:将懒加载和线程安全完美结合的一种方式(无锁)。(推荐)

 

备注:

1. 全局共享,独一份;

2. 构造函数不暴露(若是暴露便不能保证一份),本身负责本身的构造;

3. 懒汉式:Lazy load,用到才加载,非线程安全。如何保证线程安全呢:

(1) synchronized getInstance()。

(2)双重检查加锁(volatile)。

4. 饿汉式:一开始就申请好,浪费了点资源,但其线程安全。

5. Holder模式:

(1)改为内部类,由JVM保证线程安全性。

相关文章
相关标签/搜索