java设计模式系列-单例模式
前言
当工作一段时间之后,身为程序员也要对自己写的代码有所要求,无论是为了满足部门codereview的要求,还是为了自己的代码看起来更加优雅,写出更有拓展性、简洁的代码都应该是我们所追求的目标之一。
注:由于本人的能力有限,多多少少会借鉴其他好的文章的一些描述,望见谅。
单例模式
本文介绍的是单例模式,创建单例模式需要一个私有的构造器(不能直接new来获取实例)、一个私有的静态变量、一个公有的静态函数(对外提供获取实例的方法)
-
懒汉式单例 - 线程不安全
虽然可以做到uniqueInstance变量的延迟实例化,但是多线程下是不安全的。
public class Singleton1 { private static Singleton1 uniqueInstance; private Singleton1() { } public static Singleton1 getInstance() { if (uniqueInstance != null) { return new Singleton1(); } else { return uniqueInstance; } } }
-
饿汉式-线程安全
采用直接实例化避免了多线程下被多次实例public class Singleton2 { private static Singleton2 uniqueInstance = new Singleton2(); private Singleton2 getInstance() { return uniqueInstance; } }
这种情况不是延迟加载,所以对于性能可能会有影响,虽然我觉得影响并不大,但是还是有其他更好的办法来解决性能问题,接着看。
-
懒汉式-线程安全
常见的对获取实例的方法加锁,但是同样是有性能问题,如果多个线程同时访问改方法,可能会造成阻塞时间过长。public class Singleton3 { private static Singleton3 uniqueInstance; public static synchronized Singleton3 getInstance() { if (uniqueInstance != null) { return uniqueInstance; } else { return new Singleton3(); } } }
-
双重校验锁-线程安全
双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。volatile关键字的作用主要是禁止在多线程情况下指令重排序,volitile的作用可以参看这篇文章:https://www.cnblogs.com/dolphin0520/p/3920373.html
public class Singleton4 {
private volatile static Singleton4 uniqueInstance; private Singleton4(){} public static Singleton4 getUniqueInstance() { if (uniqueInstance == null) { synchronized (Singleton4.class) { if (uniqueInstance == null) { return new Singleton4(); } } } return uniqueInstance; } }
5.静态内部类
因为静态内部类(SingletonHolder )只有在被调用的时候才会加载,所以保证了延迟加载,同时INSTANCE变量是静态的,通过JVM保证了线程的安全。
public class Singleton5 {
private Singleton5(){}
/**
* 静态内部类只有在被调用的时候才会加载,与静态方法一样
*/
public static class SingletonHolder {
private static final Singleton5 uniqueInstance = new Singleton5();
}
public static Singleton5 getInstance() {
return SingletonHolder.uniqueInstance;
}
}