版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ljh_learn_from_base/article/details/72802777
/*
修改于2018-09-10 23:12
实现单例的四种方式:
饿汉式(线程安全,调用效率高,但是不能延时加载)
懒汉式(线程安全,调用效率不高,可以延时加载)
静态内部类式(线程安全,调用效率高,但是可以延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
*/
/*单例设计模式:保证一个类在使用过程中,只有一个实例。优势就是他的作用,这个类永远只有一个实例。
步骤: 1.将该类的构造方法私有;
2. 在内部实例化一个该类的实例;
3. 提供接口给外部访问。
//饿汉式://线程安全,“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象:*/
/* 这种写法不会出现并发问题,但是它是饿汉式的,在ClassLoader加载类后SingletonDemo 的实例就会第一时间被创建,
饿汉式的创建方式在一些场景中将无法使用:譬如SingletonDemo 实例的创建是依赖参数或者配置 文件的,
在getInstance()之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。 */
public class SingletonDemo {
private SingletonDemo (){} // 1.
private static final SingletonDemo single = new SingletonDemo(); // 2.
public static SingletonDemo getInstance(){ // 3.
return single;
}
}
public class Singleton2 {
/* 使用内部类来实现单例模式,线程安全
这种写法仍然使用JVM本身机制保证了线程安全问题;由于SingletonHolder是私有的,
除了getInstance()之外没有办法访问它,因此它是懒汉式的;
同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖JDK版本。*/
private Singleton2(){}
private static class SingletonHolder {
//单例对象
static final Singleton2 INSTANCE = new Singleton2();
}
public static Singleton2 getInstance() {
return SingletonHolder.INSTANCE;
}
}
//懒汉式:“懒汉式”是在你真正用到的时候才去建这个单例对象:延迟加载
使用DCL(Double checked Locking) 双重检查锁
package dao;
public class Singleton {
//Java提供了volatile关键字来保证多线程可见性,当其中一个线程对某一个值修改后,其他线程能看到
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {//使用了synchronized 同步代码块
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
/*
通过enum关键字来实现枚举,在枚举中需要注意的有:
1. 枚举中的属性必须放在最前面,一般使用大写字母表示
2. 枚举中可以和java类一样定义方法
3. 枚举中的构造方法必须是私有的
4. 通过一个java类来模拟枚举的功能:
5.
单元素的枚举类型已经成为实现Singleton的最佳实践。 */
public class Person {
private Person() {};
// 这里有几个原因关于为什么在Java中宁愿使用一个枚举量来实现单例模式:
/*
1、 自由序列化;
2、 保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量);
3、 线程安全;
*/
// 懒汉式枚举实现 Singleton
public enum Singleton {// 相当于Singleton类
INSTANCE;// 枚举里的属性相当于Singleton的实例
private Person instance;
private Singleton() {// 私有构造函数
instance = new Person();// 在构造函数中完成实例化操作
}
public Person getInstance() {// 提供公有方法对其访问
return instance;
}
}
// 使用Singleton.INSTANCE.getInstance();来调用
}