单例模式-序列号生成器
1. 序列號生成器
設計一個全局的序列號生成器,返回long類型,要求生成的序列號全局唯一且遞增。
序列號的實現(xiàn)很簡單,如下:
class SerialGenerator{private long code;// 返回下一個號碼public synchronized long next(){return ++code;} }如果不是單例,多個生成器實例生成的序列號都是從0開始,會造成沖突,優(yōu)化如下:
class SerialGenerator{private long code;private static final SerialGenerator INSTANCE = new SerialGenerator();// 私有化構(gòu)造器,防止外部newprivate SerialGenerator(){}public synchronized long next(){return ++code;}public static SerialGenerator getInstance(){return INSTANCE;} }客戶端調(diào)用:
public class Client {public static void main(String[] args) {SerialGenerator serialGenerator = SerialGenerator.getInstance();serialGenerator.next();} }這就是單例模式。
2. 單例模式的定義
確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。
單例模式屬于創(chuàng)建型模式,它的核心操作是:
也可以將靜態(tài)常量聲明為public,外部類直接訪問單例,但是不建議這么做,調(diào)用getInstance()方法來獲取實例,方便以后擴展。
3. 單例模式的擴展
上面寫的例子屬于【餓漢式】,不管客戶端是否需要訪問實例,只要Class文件被Load到內(nèi)存,實例就會被創(chuàng)建。
3.1 DCL懶漢式
DCL全稱是:Double Check Lock,雙重檢查加鎖,是【懶漢式】的一種實現(xiàn)方式。實例默認不會創(chuàng)建,只有當客戶端真正需要訪問實例時,實例才會被創(chuàng)建,重點是控制并發(fā)訪問。
public class SerialGenerator_DCL {private long code;private static volatile SerialGenerator_DCL instance;public synchronized long next() {return ++code;}public static SerialGenerator_DCL getInstance() {if (instance == null) {synchronized (SerialGenerator_DCL.class) {if (instance == null) {// recheckinstance = new SerialGenerator_DCL();}}}return instance;} }3.2 內(nèi)部類實現(xiàn)單例
【懶漢式】的另外一種實現(xiàn)方式,通過內(nèi)部類來持有實例對象,當單例類被Load時,內(nèi)部類并不會被加載,也就不會創(chuàng)建實例,只有當客戶端真正需要訪問實例時,內(nèi)部類才會被加載并創(chuàng)建實例。
public class SerialGenerator_InnerClass {private long code;private SerialGenerator_InnerClass() {}public synchronized long next() {return ++code;}private static class InnerClass {final static SerialGenerator_InnerClass INSTANCE = new SerialGenerator_InnerClass();}public static SerialGenerator_InnerClass getInstance() {return InnerClass.INSTANCE;} }3.3 單例枚舉
《Effective Java》的作者Joshua Bloch在《用私有構(gòu)造器或者枚舉類型強化Singleton屬性》一節(jié)中提出了實現(xiàn)單例的另一種方式:包含單個元素的枚舉類型。
前面寫的幾種單例實現(xiàn)方式,從嚴格意義上來說,是有“缺陷”的。通過Java的反射技術,可以調(diào)用私有構(gòu)造器創(chuàng)建多個實例,另外,反序列化也會對單例造成破壞,具體可以查看筆者的博客:《你寫的單例真的安全嗎?》。
枚舉的方式可以避免這種破壞,是實現(xiàn)單例的最佳方式:
public enum SerialGenerator_Enum {INSTANCE;private long code;public synchronized long next() {return ++code;} }4. 單例模式的優(yōu)缺點
優(yōu)點
缺點
5. 總結(jié)
單例模式算是23種設計模式中最簡單的一個了,它要求類自行實例化,并向全局提供這個實例。單例模式應用非常的廣泛,例如Spring的IOC容器中,每個Bean默認就是單例的,JDK的java.lang.Runtime就是用【餓漢式】實現(xiàn)的單例。
總結(jié)
以上是生活随笔為你收集整理的单例模式-序列号生成器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ghost 开发主题
- 下一篇: centos安装网易云音乐~