设计模式-单例模式的几种创建方式

单例模式

定义

Ensure a class has only one instance, and provide a global point of access to it.
(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例)

创建方式

创建方式分为饿汉式、懒汉式、双重检查、静态内部类、枚举等。

饿汉式

  1. 静态属性创建
/**
 * 采用饿汉式创建单例
 * 使用静态属性,如果创建后不使用,会有内存浪费
 */
class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

  1. 静态代码块创建
/**
 * 使用饿汉式创建单例对象
 * 采用静态代码块实现
 */
class Singleton {
    private static Singleton instance;

    static {
        instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

  1. 代码示例
/**
 * 使用懒汉式创建单例对象,会出现线程并发问题,不推荐使用
 */
class Singleton {
    private static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  1. 在1的基础上优化如下
/**
 * 使用懒汉式创建单例对象
 * 解决了线程并发问题,但效率低
 */
class Singleton {
    private static Singleton instance;

    private Singleton(){}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  1. 在2的基础上提升效率
/**
 * 懒汉式创建单例,线程安全,推荐使用
 * volatile作用:
 * 	1) 多线程间的数据可见性
 *  2) 防止指令重排
 * 如果不加volatile,可能会得到一个半初始化的对象(当然这种情况比较少见)
 */
class Singleton {
    private static volatile Singleton instance;

	// 对象创建比较耗时,在多线程并发时,可能对象的属性只初始化了一部分(半初始化)
    private Singleton(){
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (Exception e) {
			// 异常信息
		}
	}

    public static Singleton getInstance() {
    	// 说明:
    	// 第一个线程拿到锁后,创建对象,执行构造方法。但是只初始化到一半时,第二个线程进来判断instance == null,发现instance不为空,所以就直接返回该对象,但是这时的对象只初始化了一半(半初始化)。
    	// 这样就会有问题,所以要加volatile关键字,防止指令重排,就不会有这个问题了。
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

代码示例

/**
 * 静态内部类实现单例,线程安全,推荐使用
 */
class Singleton {
    private Singleton() {}

    private static class SingletonInstance {
        public static Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

测试类

public class SingletonTest {

    public static void main(String[] args) {
        Runnable r = () -> System.out.println(Singleton.getInstance());
        ExecutorService service = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            service.execute(r);
        }
        service.shutdown();
    }
}

枚举

代码示例

/**
 * 枚举实现单例,线程安全,推荐使用
 */
enum Singleton {
    INSTANCE
}

// 测试类
public class SingletonTest {

    public static void main(String[] args) {
        Runnable r = () -> System.out.println(Singleton.INSTANCE);
        ExecutorService service = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            service.execute(r);
        }
        service.shutdown();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值