设计模式系列——单例模式

单例模式

  单例模式(Singleton)的定义:一个类只能有一个实例,并且这个实例由这个类创建。在软件设计中,为了节约空间、保证数据的一致性,许多类只能拥有一个实例,这种设计就采用单例模式。单例模式的实现方法是:1、使类的构造方法私有化;2、创建属于此类类型的静态成员对象;3、提供静态方法获取对象。

单例模式的实现

  常用的单例模式的实现方式有4种,其中包括懒汉式、饿汉式、枚举实现、双重检测方式,下面进行介绍。

饿汉式

  该方式的特点是在加载类的时候就创建对象,此种方式是线程安全的。但是在类的创建过程复杂、繁琐时,这种方式导致类的加载过于缓慢。

/**
 * 单例模式饿汉式
 */
public class Singleton {

    private static final Singleton instance = new Singleton() ;
    private Singleton(){}

    public static Singleton getInstance(){
    	try {
            Thread.sleep(3000); //模拟创建延迟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return instance;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()->{
            ints1 = Singleton.getInstance();
        });
        Thread thread2 = new Thread(()->{
            ints2 = Singleton.getInstance();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(ints1 == ints2);
        System.out.println(ints1);
        System.out.println(ints2);
    }

}
枚举方式

  这种方式有点和饿汉式一样,都是简单实现,同时是线程安全的。

// 枚举实现方式
public enum SingletonEnum {

    Instance();
    
    SingletonEnum getInstance(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Instance;
    }
}

//测试类
public class Singleton {
    private static SingletonEnum inst1;
    private static SingletonEnum inst2;

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()->{
            inst1 = SingletonEnum.getInstance();
        });
        Thread thread2 = new Thread(()->{
            inst2 = SingletonEnum.getInstance();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(inst1 == inst2);
        System.out.println(inst1);
        System.out.println(inst2);
    }

}
懒汉式

  这种方式的特点是在需要第一次需要对象的时候加载类。为了保证线程安全,对实例对象使用volatile关键字,同时在获取实例对象的方法上使用synchronized关键字。这种方式的缺点是在方法上加锁过于频繁,其实只需要在第一次创建对象的时候需要将方法加锁,而后面获取对象的操作是不需要加锁的,这样会降低效率。

/**
 * 单例模式懒汉式
 */
public class Singleton {

    private static volatile Singleton instance = null;
    private static Singleton ints1;
    private static Singleton ints2;

    private Singleton(){}

    public static synchronized Singleton getInstance(){
    	try {
            Thread.sleep(3000); //模拟创建延迟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()->{
            ints1 = Singleton.getInstance();
        });
        Thread thread2 = new Thread(()->{
            ints2 = Singleton.getInstance();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(ints1 == ints2);
        System.out.println(ints1);
        System.out.println(ints2);
    }

}
双重检测方式

  这种方式是改造懒汉式创建方式,只在第一次创建时加锁,后面获取实例不用加锁便能获取对象,改善了获取类的效率。

**
 * 单例模式双重检测方式
 */
public class Singleton {

    private static volatile Singleton instance = null;
    private static Singleton ints1;
    private static Singleton ints2;

    private Singleton(){}

    public static Singleton getInstance(){
       if(instance == null){
           synchronized (Singleton.class){
               if(instance == null){
                   try {
                       Thread.sleep(3000); //模拟创建延时
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   instance = new Singleton();
               }
           }
       }
        return instance;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()->{
            ints1 = Singleton.getInstance();
        });
        Thread thread2 = new Thread(()->{
            ints2 = Singleton.getInstance();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(ints1 == ints2);
        System.out.println(ints1);
        System.out.println(ints2);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值