一、饿汉模式
public class Singleton1 {
//1.定义资源
private static Singleton1 instance = new Singleton1();
//2.构造函数私有化
private Singleton1() {}
//3.获取资源
public static Singleton1 getInstance() {
return instance;
}
}
类加载时就会被创建,不管实例对象有没有被用到。
二、懒汉模式
public class Singleton2 {
private static volatile Singleton2 instance = null;
private Singleton2() {}
public static Singleton2 getInstance() {
if(instance == null) {
synchronized(Singleton2.class) {
if(instance == null) {
instance = new Singleton2();
}
}
}
return instance;
}
}
1、double-check,当多个线程在等待锁时,需要再检查instance是否为null,以防创建多个对象。
2、在某个线程创建单例对象时,在构造方法被调用之前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可 以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化。若紧接着另外一个线程来调用getInstance,取到的就是状态不正确的对象,程序就会出错。volatile的一个语义是禁止指令重排序优化,也就保证了instance变量被赋值的时候对象已经是初始化过的,从而避免了上面说到的问题。
三、使用静态内部类
public class Singleton3 {
private Singleton3() {}
private static class SingletonHolder{
private static Singleton3 instance = new Singleton3();
}
public static Singleton3 getInstance() {
return SingletonHolder.instance;
}
}
四、枚举
public enum Singleton4 {
INSTANCE;
public static void whateverMethod() {}
}
防止反序列化之后都会生成多个实例,防止反射修改。
单例模式的优点:
(1)节约资源
(2)让不同线程共享信息,适用于多个模块共享同一对象
单例模式的应用:
全局计数器
管理类如各种资源池(线程池、连接池),Windows任务管理器
配置信息类