二十三种设计模式之单例模式
饿汉式:
对象在类加载的时候就创建好
优点:这种创建模式编写简单,该类在加载的时候就会创建好对象的实例,所以不用考虑线程同步的问题
缺点:如果从始至终就没有使用该对象,则会浪费内存空间
//1.创建私有化构造器,防止用户在其他类中通过new关键字实例化本类的对象
private singleton() {}
//2.在本类中实例化一个对外提供的对象,使用final static定义之后,实例化对象会在类加载之前就创建好
private final static singleton s = new singleton();
//3.提供一个公有的方法获取实例化的对象
public static singleton getInstance() {
return s;
}
在第二步,我们也可以使用静态代码块来创建实例对象,在这里我们就不能够使用final关键字,因为如果static关键字和final关键字连用,就必须在创建对象的引用的时候,对对象引用进行初始化,且之后不可改变。
private static singleton s;
static {
s = new singleton();
}
线程安全的懒汉式:
对象只有在需要的时候才进行实例化,为了保证在多线程时的线程安全问题,在懒汉式的基础上添加线程锁,保证在同一时段只会有一个线程使用创建对象的方法
优点:节省了空间,并且线程安全
缺点:效率太低
//1.创建私有的构造器
private Singleton02() {}
//2.创建该类的引用,注意这里不能使用关键字final,否则会变成饿汉式
private static Singleton02 s = null;
//3.创建向外提供对象的方法
public static synchronized Singleton02 getInstance() {
//4.判断对象是否创建,如果对象为空则为该引用创建一个实例对象
if(s == null) {
s = new Singleton02();
}
return s;
}
Double Check Lock:
双重检查,使用关键字volatile,当使用该关键字声明的变量一旦发生改变,就会立即将更新的操作通知到其他线程
//关键字volatile,通过该关键字,当当前声明的变量发生改变时,会通知其他线程进行改变
private static volatile Singleton03 s;
public static Singleton03 getInstance() {
//进行第一次判断,s是否为空,若s为空不创建,保证的是对象创建之后,其他线程直接返回来提高效率的问题
if(s == null) {
//创建线程锁,保证线程的安全
synchronized (Singleton03.class) {
//再次进行判断,保证执行的线程中s仍然为null
if(s == null) {
s = new Singleton03();
}
}
}
return s;
}
静态内部类加载:
在当前类进行加载的时候,不会先对内部静态类进行加载。当之后调用内部静态类的成员变量或方法的时候,静态内部类才会加载。并且由于是静态的缘故,静态内部类只会在第一次初始化的时候进行加载,所以不用考虑线程安全的问题。
//创建内部静态类
private static class singletonInstance{
private static final singleton04 singleton = new singleton04();
}
//由于是静态的缘故,可以直接使用类名调用
public static singleton04 singleton04() {
return singletonInstance.singleton;
}
枚举实现:
直接通过枚举类实现单例模式,这是最简单的实现方式
优点:解决了线程安全的问题,同时可以防止使用反序列化创建对象
enum singletonEnum{
INSTANCE;
//方法
public void says() {
System.out.println("创建成功");
}
}