单例模式

单例模式: 保证一个类只有一个实例, 并提供一个全局访问点。(可以说是最简单的模式, 从零单排冲天梯)大笑



类图:


抽象实现:


1. 懒汉模式 (懒得判断是否已经实例化, 先进行实例化)

[java]  view plain copy
  1. package com.wenniuwuren.singleton;  
  2.   
  3. public class Singleton {  
  4.       
  5.     // 懒汉模式  
  6.     /** 
  7.      * 私有且唯一的属性 
  8.      */  
  9.     private static Singleton uniqueInstance = new Singleton();  
  10.       
  11.     /** 
  12.      * 私有构造器保证不能被继承 
  13.      */  
  14.     private Singleton() {  
  15.           
  16.     }  
  17.       
  18.     /** 
  19.      * 全局访问点  static的修饰至关重要--提供给外部在不能实例化内部代码的时候通过类名访问内部public方法 
  20.      */  
  21.     public static Singleton getInstance() {  
  22.         return uniqueInstance;  
  23.     }  
  24.       
  25.       
  26.       
  27. }  
适用于对程序性能有较大要求的地方, 如果用饱汉模式(详情见下文)要对线程加同步锁降低系统性能。



2. 饱汉模式(采用了volatile和同步块来保证并发安全性, 不像上面的懒汉模式直接就实例化了, 因为饱汉模式存在着判断和赋值,所以必须加上安全机制保障并发的正确性。 例如:线程A判断uniqueInstance为null进入方法, 然后new了实例, 但是还没赋值给uniqueInstance, 这时CPU把时间给了线程B, 此时的uniqueInstance还未赋值所以又new了一次实例, 那么这就破坏了单例模式了)

[java]  view plain copy
  1. package com.wenniuwuren.singleton;  
  2.   
  3. public class Singleton {  
  4.   
  5.       
  6.     // 饱汉模式  
  7.     /** 
  8.      * 私有且唯一的属性   
  9.      * volatile修饰符保证变量仅存在于内存, 每个线程仅在内存中共享该变量, 从而保证了并发的安全性 
  10.      */  
  11.     private volatile static Singleton uniqueInstance = null;  
  12.       
  13.     /** 
  14.      * 私有构造器保证不能被继承 
  15.      */  
  16.     private Singleton() {  
  17.           
  18.     }  
  19.       
  20.     /** 
  21.      * 全局访问点 
  22.      */  
  23.     public static Singleton getInstance() {  
  24.         if (uniqueInstance == null) {  
  25.             // 为空时才进行创建实例(延迟创建实例有助于节省不必要的资源占用)  
  26.             synchronized (Singleton.class) {  
  27.                 if (uniqueInstance == null) {  
  28.                     return uniqueInstance = new Singleton();  
  29.                 }  
  30.             }  
  31.         }  
  32.         return uniqueInstance;  
  33.     }  
  34.       
  35. }  

当然如果系统对性能要求不高, 饱汉模式可以不像上面那么复杂, 直接在getInstance()方法上加同步修饰字段synchronized即可。



但是上面的方法虽然已经把同步代码块缩减到最小, 但是还是对性能有一点影响, 接下来介绍另一种保障线程安全的方法并且不使用同步代码块和volatile字段修饰。

[java]  view plain copy
  1. public class Singleton {  
  2.       
  3.     private Singleton(){}  
  4.     /** 
  5.      *    类级的内部类,只有被调用到时才会实例化 
  6.      */  
  7.     private static class SingletonHolder{  
  8.         private static Singleton instance = new Singleton();  
  9.     }  
  10.       
  11.     public static Singleton getInstance(){  
  12.         return SingletonHolder.instance;  
  13.     }  
  14. }  


应用场景:              

                - 网站的计数器, 不然并发计数访客什么的数量肯定会乱

                - 应用程序的日志, 并发写日志不控制安全性日志重复写入多次

                - Spring中的Bean默认也是单例的



参考书籍: 

                  《设计模式:可复用面向对象软件的基础》

                  《Java并发编程实战》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值