Singleton 单例模式

饿汉式单例模式
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:01
 *
 * @author sheting
 */
public class EagerInitializedSingleton {

    /**
    立即生成单例对象
     */
    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();

    /**
     * private constructor to avoid client applications to use constructor
     */
    private EagerInitializedSingleton(){}

    public static EagerInitializedSingleton getInstance(){
        return instance;
    }
}

饿汉式单例模式 通过静态代码块增加异常处理
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:03
 *
 * @author sheting
 */
public class StaticBlockSingleton {

    private static StaticBlockSingleton instance;

    private StaticBlockSingleton(){}

    //增加异常处理
    static{
        try{
            instance = new StaticBlockSingleton();
        }catch(Exception e){
            throw new RuntimeException("Exception occured in creating singleton instance");
        }
    }

    public static StaticBlockSingleton getInstance(){
        return instance;
    }

}

懒汉式单例模式 存在线程安全问题
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:04
 *
 * @author sheting
 */
public class LazyInitializedSingleton {

    private static LazyInitializedSingleton instance;

    private LazyInitializedSingleton(){}

    //存在线程安全问题
    public static LazyInitializedSingleton getInstance(){
        if(instance == null){
            instance = new LazyInitializedSingleton();
        }
        return instance;
    }

}

懒汉式单例模式 解决线程安全问题
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:06
 *
 * @author sheting
 */
public class ThreadSafeSingleton {

    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton(){}

    public static synchronized ThreadSafeSingleton getInstance(){
        if(instance == null){
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }

    //和上面的方法相比,性能提升了,因为synchronized只获取一次,上面方法,每次调用getInstance都要检查锁
    public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
        if(instance == null){
            synchronized (ThreadSafeSingleton.class) {
                if(instance == null){
                    instance = new ThreadSafeSingleton();
                }
            }
        }
        return instance;
    }
}

内部静态类实现的单例模式
package com.sheting.design.pattern.creational.singleton;

import com.sheting.singleton.Singleton;

/**
 * Create Time: 2018-03-17 10:14
 *
 * @author sheting
 */
public class BillPughSingleton {

    private BillPughSingleton(){}

  /*
    Notice the private inner static class that contains the instance of the singleton class.
    When the singleton class is loaded, SingletonHelper class is not loaded into memory and only when someone calls the getInstance method,
    this class gets loaded and creates the Singleton class instance.

    This is the most widely used approach for Singleton class as it doesn’t require synchronization.
    I am using this approach in many of my projects and it’s easy to understand and implement also.
    */

    //内部静态类实现单例
    private static class SingletonHelper{
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }

    public static BillPughSingleton getInstance(){
        return SingletonHelper.INSTANCE;
    }

}

枚举天然的单例模式
package com.sheting.design.pattern.creational.singleton;

/**
 * Create Time: 2018-03-17 10:21
 *
 * @author sheting
 */
public enum EnumSingleton {

    //枚举三个特性,自由序列化,线程安全,保证单例。
    INSTANCE;

    public static void doSomething(){
        //do something
    }
}

单例对象 实现序列化接口 不实现readResolve(),返回的hashCode值不一样
package com.sheting.design.pattern.creational.singleton;

import java.io.*;

/**
 * Create Time: 2018-03-17 10:33
 *
 * @author sheting
 */
public class SingletonSerializedTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerializedSingleton instanceOne = SerializedSingleton.getInstance();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
        out.writeObject(instanceOne);
        out.close();

        //deserailize from file to object
        ObjectInput in = new ObjectInputStream(new FileInputStream("filename.ser"));
        SerializedSingleton instanceTwo = (SerializedSingleton) in.readObject();
        in.close();

        System.out.println("instanceOne hashCode="+instanceOne.hashCode());
        System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());


      /* API解释:
      从 ObjectInputStream 读取“非共享”对象。此方法与 readObject 类似,
      不同点在于它可以防止对 readObject 和 readUnshared 的后续调用返回对通过此调用获取的反序列化实例的附加引用。尤其是:
         如果调用 readUnshared 反序列化反向引用(以前写入流的对象的流表示形式),则抛出 ObjectStreamException。
         如果 readUnshared 成功返回,则反序列化对由 readUnshared 反序列化的流句柄的反向引用的任何后续尝试,都将导致抛出 ObjectStreamException。
      通过 readUnshared 反序列化一个对象使得与返回对象关联的流句柄无效。
      注意,此操作本身不能始终保证由 readUnshared 返回的引用是唯一的;反序列化对象可能定义一个 readResolve 方法,
      该方法将返回一个对其他方可见的对象,或者 readUnshared 可能返回一个从流中其他地方或通过外部方法获得的 Class 对象或 enum 常量。
      如果反序列化对象定义一个 readResolve 方法并且该方法的调用返回一个数组,则 readUnshared 返回该数组的浅表副本;
      此规则保证返回的数组对象是唯一的,不能通过对 ObjectInputStream 调用 readObject 或 readUnshared 再次获得,即使能操纵底层数据流时也是如此。

      重写此方法的 ObjectInputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;
      在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。

        */
    }
}

class SerializedSingleton implements Serializable {

    private static final long serialVersionUID = -7604766932017737115L;

    private SerializedSingleton(){}

    private static class SingletonHelper{
        private static final SerializedSingleton instance = new SerializedSingleton();
    }

    public static SerializedSingleton getInstance(){
        return SingletonHelper.instance;
    }

     //重要   
    protected Object readResolve() {
        return getInstance();
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,602评论 18 399
  • 前言 最先接触编程的知识是在大学里面,大学里面学了一些基础的知识,c语言,java语言,单片机的汇编语言等;大学毕...
    oceanfive阅读 3,049评论 0 7
  • 什么是爱?曾经听过一个笑话,把好吃的给她吃,把好玩的给她玩,这就是爱,或许童年的爱才是最纯碎、最无瑕的吧。然而,随...
    九说阅读 537评论 2 4
  • 文/源河 她们被叫做姑娘 正如她们花一样的年纪 那些花儿 或许可以 静悄悄地 绽放在美丽的山谷 迎着阳光和雨露,尽...
    源河阅读 337评论 0 0
  • 在何晏小的时候,父亲去世,母亲尹氏因才貌出众,被曹操选入宫,做妾。曹操一直很宠爱他,但他还是嫌弃。 长大以后的何晏...
    应舒与蔚阅读 368评论 0 2