首页 > 经验记录 > java设计模式_单例模式

java设计模式_单例模式

单例模式
核心作用:

  • 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

 
常见的几种单例模式实现方式

  • 饿汉式(线程安全,调用效率高。但是不能延时加载。)
  • 懒汉式(线程安全,调用效率不高。但是可以延时加载)
  • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题。不建议使用)
  • 静态内部类式(线程安全,调用效率高,可以延时加载)
  • 枚举单例(线程安全,调用效率高。不能延时加载)

 
 
饿汉式实现:

package com.yibobo.singleton;
/**
 * 测试饿汉式的单例模式
 * @author pyb www.yibobo.top
 */
public class SingletonDemo01 {
    //类初始化时,立即加载对象!由于加载类时线程是天然安全的所以无需同步
    private static SingletonDemo01 s = new SingletonDemo01();
    private SingletonDemo01(){}//私有化构造器
    //方法没有同步,效率高!
    public static SingletonDemo01 getInstance(){
        return s;
    }
}
package com.yibobo.singleton;
public class Test {
    public static void main(String[] args) {
        SingletonDemo01 s1 = SingletonDemo01.getInstance();
        SingletonDemo01 s2 = SingletonDemo01.getInstance();
        System.out.println(s1==s2);//结果为true
    }
}

 
饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题,因此可以省略synchronize关键字。
问题:如果只是加载该类,而不是要调用getInstance()方法,甚至永远没有调用,则会造成资源浪费。
 
懒汉式实现:
 

package com.yibobo.singleton;
/**
 * 测试懒汉式的单例模式
 * @author pyb www.yibobo.top
 */
public class SingletonDemo02 {
    //类初始化时,并不初始化对象,延时加载,真正要用的时候在加载
    private static SingletonDemo02 s;
    private SingletonDemo02(){}//私有化构造器
    //在调用getInstance()方法时,在判定new不new
    //方法同步,调用效率较低
    public static synchronized SingletonDemo02 getInstance(){
        if (s == null){
            s = new SingletonDemo02();
        }
        return s;
    }
}

 
延时加载!懒加载,真正用的时候才加载
问题:资源利用效率高了。但是,每次调用getInstance()方法时都要同步,并发效率较低
 
 
 
静态内部类式(也是一种懒加载方式):

package com.yibobo.singleton;
/**
 * 测试静态内部类式的单例模式
 * 这种方式线程安全、调用效率高且实现延时加载。需要延时加载时,静态内部类式好于懒汉式
 * @author pyb www.yibobo.top
 */
public class SingletonDemo03 {
    private SingletonDemo03(){}//私有化构造器
    //类加载的过程天然线程安全
    private static class SingletonClassInstance{
        private static final SingletonDemo03 instance = new SingletonDemo03();
    }
    //无需同步,且用到时才会创建出对象。兼顾并发效率与延时加载
    public static SingletonDemo03 getInstance(){
        return SingletonClassInstance.instance;
    }
}

 
要点:

  • 外部类没有static属性,则不会像饿汉式那样立即加载对象。
  • 只有真正调用getInstance(),才会加载静态内部类。加载类是是线程安全的。Instance是static final类型,保证了内存中只有一个实例存在且只能被赋值一次,从而保证了线程安全性
  • 兼备了并发高效调用和延迟加载的优势!

 
枚举式:

package com.yibobo.singleton;
/**
 * 测试枚举式的单例模式
 * 由于枚举本身就是个单列,这种方式线程安全、调用效率高
 * 但不能实现延时加载。在不需要延时加载的情况下枚举类好于饿汉式(但枚举用的人少)
 * @author pyb www.yibobo.top
 */
public enum SingletonDemo04 {
    INSTANCE;
    //下面就随便写这个类的方法
}

 
 
Double-Check双重锁定式,这种方式有问题,但是我看百度上说JDK1.5之后添加了一个关键字:volatile,这个可以解决双重锁定式的问题。自个研究吧
还是写一下

package com.yibobo.singleton;
/**
 * 测试双重检查+锁的单例模式
 * 这种方式线程安全、调用效率高且实现延时加载。
 * @author pyb www.yibobo.top
 */
public class SingletonDemo05 {
	//类初始化时,并不初始化对象,延时加载,真正要用的时候在加载
	private static volatile SingletonDemo05 s = null;
	private SingletonDemo05(){}
	//这个模式将同步内容下放到if内部,提高了执行的效率
        //不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。
	public static SingletonDemo05 getInstance() {
		if (s == null) {
			synchronized (SingletonDemo05.class) {
				if (s == null) {
					s = new SingletonDemo05();
				}
			}
		}
		return s;
	}
}

 

           


CAPTCHAis initialing...
EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00