码迷,mamicode.com
首页 > 其他好文 > 详细

单例模式

时间:2016-06-28 02:00:40      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:

作用


保证一个类只有一个实例,并且向外提供一个访问点。

应用场景


windows中的任务管理器就是一个很典型的单例模式。

读取配置文件的类一般只new一个对象,没必要在每次读取配置文件时重新new一个对象。

网站计数器也采用单例模式,否则很难同步

应用程序的日志文件通常只用一个对象来维护

数据库链接池的设计也采用单例模式。

文件系统也是一个单例模式,一个操作系统只能有一个文件系统。

在Spring中,每个Bean默认是单例的,这样Spring容器易于管理。

javaweb中的每个Servlet都是一个单例

优点


 

因为只产生一个实例,所以减少了系统开销。可以在系统设置全局访问点,优化共享资源访问。

分类


主要  

  • 饿汉式(线程安全,调用效率高,但不能延时加载)

  • 懒汉式(线程安全,调用效率不高,可以延时加载)

其它

  • 双重检测锁式 (由于JVM的原因,有时会出现问题)
  • 静态内部类式(线程安全,调用效率高,可以延时加载)
  • 枚举单例(线程安全,调用效率不高,不能延时加载)

 举例


  • 饿汉式

一上来就创建对象,立即加载,存在的问题就这个对象可能会一直用不到,白白浪费内存资源

package com.dy.xidian;

public class SingleDemo1 {
    //类初始化是立即加载对象
    //jvm只会将类加载一次,在加载类时就创建了一个实例
    private static SingleDemo1 instance = new SingleDemo1();
    //构造器私有化,不能被new对象
    private SingleDemo1(){
    }
    
    //对外提供一个访问接口,因为只有一个实例存在,所以线程安全
    public static SingleDemo1 getInstance(){return instance;}
}
  • 懒汉式

用时才创建对象,延时加载。因为加入了同步机制,所以调用效率不高

package com.dy.xidian;

public class SingleDemo2 {
    private static SingleDemo2 instance;
    private SingleDemo2() {

    }
    // 在调用的时候才会实例化一个对象
    // 存在竞态条件,应进行同步
    public static synchronized SingleDemo2 getInstance() {
        if (instance == null)
            instance = new SingleDemo2();
        return instance;
    }
}

 

  •  双重检测锁实现

将同步块放到了方法的内部,这样不仅能延时加载,而且提高的调用效率。但是由于编译器优化以及JVM底层内部模型原因,偶而会出现问题,不建议使用

package com.dy.xidian;

public class SingleDemo3 {
    private static SingleDemo3 instance;
    private SingleDemo3() {
    }

    public static SingleDemo3 getInstance() {
        if (instance == null) {
            SingleDemo3 sc;
            synchronized (SingleDemo3.class) {
                sc = instance;
                if(sc == null){
                    synchronized (SingleDemo3.class) {
                        if(sc == null)
                            sc = new SingleDemo3();
                    }
                }
                instance = sc;
            }
        }
        return instance;
    }
}

 

  • 静态内部类模式

JVM初始化类SingleDemo4时并不会去初始话其内部内,所以避免了向饿汉式那样立即加载对象。

只有真正调用getInstance(),才会加载内部类。加载类时是线程安全的,而final能保证内存中只有这样一个实例存在,兼备了高效调用与延迟加载的优势。

package com.dy.xidian;

public class SingleDome4 {
    private SingleDome4(){}
    
    private static class SingleClassInstance{
        private static final SingleDome4 instance = new SingleDome4();
    }
    
    public static SingleDome4 getInstance(){
        return SingleClassInstance.instance;
    }
}
  • 枚举方式

枚举类本来就是单例的,但是它不能延时加载

package com.dy.xidian;

public enum SingleDome4 {
    INSTANCE;
    String a = new String();
    // 处理方法
    public static void main(String[] args) {
        System.out.println(SingleDome4.INSTANCE);
        SingleDome4.INSTANCE.a = "ff";
        System.out.println(SingleDome4.INSTANCE.a);
    }
}

 

单例模式

标签:

原文地址:http://www.cnblogs.com/xidongyu/p/5621992.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!