Java 单例模式

单例模式:

单例模式可以确保系统中某个类只有一个实例,该类自行实例化并向整个系统提供这个实例的公共访问点,除了该公共访问点,不能通过其他途径访问该实例。单例模式的优点在于:

  • 系统中只存在一个共用的实例对象,无需频繁创建和销毁对象,节约了系统资源,提高系统的性能
  • 可以严格控制客户怎么样以及何时访问单例对象。

单例模式的写法有好几种,主要有三种:

  • 懒汉式单例
  • 饿汉式单例
  • 登记式单例

实现代码:

package com.model.singleton;

/**
 * 单例模式
 * 
 * @author haveman.lv
 */
public class Singleton {

    private static Singleton          lazySingleton         = null;
    private static volatile Singleton volatileLazySingleton = null;
    private static final Singleton    HUNGRY_SINGLETON      = new Singleton();

    private Singleton(){
    }

    /**
     * 饿汉模式
     */
    /*public static Singleton getInstance() {
        return HUNGRY_SINGLETON;
    }*/

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

    /**
     * 同步锁<br>
     * 线程安全,性能低
     */
    public static synchronized Singleton getInstanceBySync() {
        if (lazySingleton == null) {
            lazySingleton = new Singleton();
        }

        return lazySingleton;
    }

    /**
     * 双重锁定检查,没有性能问题<br>
     * 需要用到 volatile 关键字,禁止指定重排序<br>
     * <br>
     * 指定重排序:由于构造方法不是一个原子操作,编译后会生成多条字节码指令,<br>
     * 由于 JAVA的 指令重排序,可能会先执行 singleton 的赋值操作,<br>
     * 该操作实际只是在内存中开辟一片存储对象的区域后直接返回内存的引用,<br>
     * 之后 singleton 便不为空了,但是实际的初始化操作却还没有执行。<br>
     * 如果此时线程B进入,就会拿到一个不为空的但是没有完成初始化的singleton 对象
     */
    public static Singleton getInstanceByDbCheck() {
        if (volatileLazySingleton == null) {
            synchronized (Singleton.class) {
                if (volatileLazySingleton == null) {
                    volatileLazySingleton = new Singleton();
                }
            }
        }

        return volatileLazySingleton;
    }

    /**
     * 静态内部类,提供实例化支持<br>
     * 线程安全,无性能问题
     * 
     * @author haveman.lv
     */
    public static class LazyHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static final Singleton getInstanceByInnerClass() {
        return LazyHolder.INSTANCE;
    }

    // ================server method===============

    public void sayHello() {
        System.out.println("Hello World!");
    }

}
package com.model.singleton;

import java.util.HashMap;
import java.util.Map;

/**
 * 单例管理器
 * 
 * @author haveman.lv
 */
public class SingletonManagement {

    private static Map<String, Singleton> map                 = new HashMap<>();
    public static String                  DEFAULT_SINGLE_NAME = "default";

    private SingletonManagement(){
    }

    public static Singleton getInstance(String name) {
        if (name == null || name.length() <= 0){
            name = DEFAULT_SINGLE_NAME;
        }
        
        if (map.get(name) == null){
            map.put(name, Singleton.getInstanceByInnerClass());
            System.out.println("initial singleton by management, name is " + name);
        }
        
        return map.get(name);
    }

}

测试:

package com.model.singleton;


public class Test {

    public static void main(String[] args) {
        Singleton s1 = SingletonManagement.getInstance(null);
        s1.sayHello();

        Singleton s2 = SingletonManagement.getInstance("s2");
        s2.sayHello();

        Singleton s3 = SingletonManagement.getInstance(null);
        s3.sayHello();

    }

}

输出结果:

initial singleton by management, name is default
Hello World!
initial singleton by management, name is s2
Hello World!
Hello World!

参考自:Java设计模式之创建型:单例模式_张维鹏的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值