单例模式特点
1、单例类只能有一个实例对象。
2、单例类必须自创唯一实例。
3、单例类必须给所有其他对象提供全局访问点。
1.饿汉式的单例模式
public class Singleton{
//创建唯一实例
private static final Singleton singleton = new Singleton();
//构造方法私有化 不允许外部创建该类对象
private Singleton(){
};
//提供全局访问点
public static Singleton getSingleton(){
return singleton;
}
}
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
2.懒汉式的单例模式
1.不考虑线程安全的懒汉式单例
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {
}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
2.为了保证懒汉模式的线程安全,有两种方式
1.双重检验锁定 + volatile关键字
思想 :双重检验锁定保证了线程唯一; 使用volatile修饰声明的单例对象可禁止jvm虚拟机的重排序,否则在并发的情况下有可能会返回空对象
代码实现
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {
};
private volatile static Singleton singleton=null;
//静态工厂方法
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
2.静态内部类
静态内部类加载方式是classLoader,jvm在初始化这个类的时候,他本身就会保证只有一个线程初始化这个类,就算创建这个对象的过程中发生了重排序那这个时候也没问题因为她时间只有一个线程去加载这个类,他只有加载好了才能对外提供,所以其他线程根本就拿不到这个对象
以上纯属逼逼叨,下面是总结
静态内部类的加载方式是classLoader,创建单例对象,保证了线程访问对象的唯一性,即保证了线程安全
public class Singleton {
private static class LazyHolder {
private static final Singleton singleton = new Singleton();
}
private Singleton (){
};
public static final Singleton getInstance() {
return LazyHolder.singleton ;
}
}