java:单例的理解

前言:Java的单例经常用到,今天发现自己有一点新的认识。

懒汉式单例

package com.mwq.singleton;

public class Singleton1 {
    private Singleton1() {

    }

    private static Singleton1 single = null;

    public static Singleton1 getInstance() {
        if (single == null) {
            return new Singleton1();
        }
        return single;
    }

    public String sayHello() {
        return "hello singleton1" + this;
    }
}

这种方式是在第一次使用的时候进行一次单例的实例化,我以前也习惯用这种方式,却不曾想这是线程不安全的,后面会写实例证明。对于private static Singleton1 single = null; 为什么没有加final关键字,因为这种懒汉式写法与final无关!

饿汉式单例

package com.mwq.singleton;

public class Singleton2 {
    private Singleton2() {

    }

    private static final Singleton2 single = new Singleton2();

    public static Singleton2 getInstance() {
        return single;
    }

    public String sayHello() {
        return "hello singleton2" + this;
    }
}

这种方式在类创建的同时就进行了实例化,私有构造器仅仅被调用一次,这就保证它是安全的。

枚举式单例

package com.mwq.singleton;

public enum Singleton3 {
    INSTANCE;

    public String sayHello() {
        return "hello singleton3" + this;
    }
}

写法更快捷,我之前也未曾知道。

无偿地提供了序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候,无疑是最佳的singleton实现方式。—–effective Java一书

对于前面两种是有可能被借助setAcceessible() 方法进行反射攻击的,但是我没有找到怎么避免?????

论证

package com.mwq.singleton;

public class Test extends Thread{
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new Test()).start();
        }
    }

    @Override
    public void run() {
        System.out.println(Singleton1.getInstance().sayHello());
        System.out.println(Singleton2.getInstance().sayHello());
        System.out.println(Singleton3.INSTANCE.sayHello());
        System.out.println();
    }
}

通过以上的方法进行测试,得出如下内容:

hello [email protected]1b1aa65
hello [email protected]1125127
hello singleton3INSTANCE

hello singleton1com.mwq.singleton.Singleton1@bb7465
hello [email protected]2a5330
hello [email protected]1125127
hello singleton3INSTANCE

hello [email protected]1125127
hello singleton3INSTANCE

可以看出来懒汉式单例的确是不安全的,会创建多次实例,第二种和第三种是安全的。

总结:本文参考了JAVA设计模式之单例模式博客,以及《effective Java 中文版》一书。

时间: 2024-10-26 22:51:50

java:单例的理解的相关文章

java单例-积木系列

一步步知识点归纳吧,把以前似懂非懂,了解表面,知道点不知道面的知识归一下档. 懒汉式单例: 私有化构造函数,阻止外界实例话对象,调用getInstance静态方法,判断是否已经实例化. 为什么是懒汉,因为它是属于延迟加载这个实例的,也就是说不用到的时候,不实例化对象的. public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInst

Java单例设计模式的实现

1. 单例设计模式的定义 单例设计模式确保类只有一个实例对象,类本身负责创建自己的对象并向整个系统提供这个实例.在访问这个对象的时候,访问者可以直接获取到这个唯一对象而不必由访问者进行实例化. 单例设计模式保证了全局对象的唯一性,在许多场景中都有应用.例如Windows中多个进程或线程同时操作一个文件的时候,所有的进程或线程对于同一个文件的处理必须通过唯一的实例来进行. 2. java单例设计模式的几种实现方式 单例设计的最大特点是类的构造函数是私有的,确保了只能由类本身创建对象,而访问者无法进

java单例类/

java单例类  一个类只能创建一个实例,那么这个类就是一个单例类 可以重写toString方法 输出想要输出的内容 可以重写equcal来比较想要比较的内容是否相等 对于final修饰的成员变量 一但有了初始值,就不能被重新赋值 static修饰的成员变量可以在静态代码块中 或申明该成员时指定初始值 实例成员可以在非静态代码块中,申明属性,或构造器中指定初始值 final修饰的变量必须要显示初始化 final修饰引用变量不能被重新赋值但是可以改变引用对象的内容分(只要地址值不变) final修

Java 单例

最近在网上看到一篇关于 Java 单例的创建问题,虽然是一个 Java 程序员,但是到现在还没有真正的深入了解到 Java 的原理和机制.所以每每看到这样能够"真正"接触 Java 的机会内心总是充满了欣喜.记录下,以后备用. 懒汉模式 public class Singlton{ private static Singleton instance; private Singlton(){} public static Singlton getInstance(){ if(instac

Java单例的实现

1.声明实例变量(静态) 2.私有化构造函数 3.创建获取实例的方法 public class Singleton{ //创建实例变量 private static Singleton singleton; //私有化构造函数 private Singleton(){ } //创建获取实例的方法 public static Singleton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singl

从一个简单的Java单例示例谈谈并发

一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static UnsafeLazyInitiallization instance; private UnsafeLazyInitiallization() { } public static UnsafeLazyInitiallization getInstance(){ if(instance==null){ /

从一个简单的Java单例示例谈谈并发 JMM JUC

原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static UnsafeLazyInitiallization instance; private UnsafeLazyInitiallization() { } public static U

Java 单例真的写对了么?

单例模式是最简单的设计模式,实现也非常“简单”.一直以为我写没有问题,直到被 Coverity 打脸. 1. 暴露问题 前段时间,有段代码被 Coverity 警告了,简化一下代码如下,为了方便后面分析,我在这里标上了一些序号: private static SettingsDbHelper sInst = null; public static SettingsDbHelper getInstance(Context context) { if (sInst == null) { // 1 s

如何写出面试官欣赏的Java单例

单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 今天我们不谈单例模式的用途,只说一说如果在面试的时候面试官让你敲一段代码实现单例模式的情况下怎样写出让面试官眼前一亮的单例代码.因为笔者学的是Java,所以接下来的实例将用Java语言编写. 说到单例模式,第一个想到的是该类中有一个初始化为null的自身引用,且被private修饰符修饰,其它类不得直接访问.除此之外,单例模式的类还需要有private的构造方法,这一点