单例模式
一、介绍
- 所谓类的单例模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
二、单例模式的八种方式
1、饿汉式(静态常量)
1)优点:写法简单,在类装载的时候完成了实例化,避免了线程同步问题
2)缺点:如果从始至终不用这个实例,则会造成内存的浪费
3)代码
class Singleton {
//1、构造器私有化,外部不能new
private Singleton() {
}
//2、本类内部创建对象实例
private final static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
2、饿汉式(静态代码块)
1)优缺点和上面的方法一致
2)代码
class Singleton {
//1、构造器私有化,外部不能new
private Singleton() {
}
//2、本类内部创建对象实例
private static Singleton instance;
static { //在静态代码块中创建单例对象
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
3、懒汉式(线程不安全)
1)优点:起到了懒加载的效果
2)缺点:只能在单线程下使用
3)代码
class Singleton {
private static Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时采取创建instance,即懒汉式
public static Singleton getInstance() {
if(instance == null) {//如果一个线程进入这条语句但还没往下执行,另一个线程也通过了这个判断语句,这样便会产生多个实例,所以在多线程环境下不可以使用这种方式
instance = new Singleton();
}
return instance;
}
}
4、懒汉式(线程安全)
1)优缺点:与上类似,解决了线程不安全的问题,但是效率很低,执行getInsance()方法都要进行同步,其实这个方法只执行一次实例化就够了
2)代码
class Singleton {
private static Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时采取创建instance,即懒汉式
public static synchronized Singleton getInstance() { //加入了同步处理的代码,解决了线程安全的问题
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
5、懒汉式(同步代码块)
if(instance == null) {
synchronized(Singleton.class) { //达不到线程安全的效果,因为只要一个线程创建完成实例,另外的线程也可以创建了
instance = new Singleton();
}
return instance;
}
6、双重检查
1)优缺点:很完美地解决了以上的问题
2)代码
class Singleton {
private static volatile Singleton instance;//关键字volatile是为了防止指令重排
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) { //双重检查
instance = new Singleton();
}
}
}
return instance;
}
}
7、静态内部类
1)优点:很完美地解决问题了
2)代码
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
private static class SingletonInstance {
//静态内部类在 Singleton类装载的时候是不会创建的
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
//这个时候才会实例化静态内部类,jvm装载类的时候是线程安全的,利用这个机制达到线程安全
return SingletonInstance.instance;
}
}
8、枚举
1)优点:推荐使用
2)代码
enum Singleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok!");
}
}