什么是单例?
单例模式属于创建型模式,它提供了一种创建对象的最佳方式。
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
1.饿汉式-----非线程安全
优点:类加载的时候创建一次实例,避免了多线程同步问题
缺点:即使单例没被用到也会创建,浪费内存
public class Singleton {
private static Singleton instance = new Singleton();
// 1.构造方法私有化,外部不能new
private Singleton() {
}
//2.直接创建对象实例
public static Singleton getInstance() {
return instance;
}
}
2.饿汉式----线程安全
public class SynchronizedSingleton {
private static SynchronizedSingleton instance=new SynchronizedSingleton();
private SynchronizedSingleton(){
}
public static SynchronizedSingleton getInstance(){
return instance;
}
}
3.懒汉式----非线程安全
优点:调用getInstance()先判断储存实例的变量是否有值,如果有直接使用,没有就创建实例将值赋给实例的变量;
缺点:没有考虑线程安全问题,多个线程并发调用getInstance,可能会创建多个实例
public class Singleton {
//2.本类内部创建对象实例
private static Singleton instance = null;
// 1.构造方法私有化,外部不能new
private Singleton() {
}
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4.懒汉式----线程安全
缺点:性能问题,添加了synchronized会比一般方法慢,如果多次调用getInstance,累积的性能损耗比较大。
public class SynchronizedSingleton {
private static SynchronizedSingleton instance = null;
private SynchronizedSingleton() { }
public synchronized static SynchronizedSingleton getInstance() {
if (instance == null) {
instance = new SynchronizedSingleton();
}
return instance;
}
}
5.静态类内部加载(线程安全)
使用内部类,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的。
public class StaticSingleton {
private static class SingletonDepth{
private static StaticSingleton instance=new StaticSingleton();
}
private StaticSingleton(){}
public static StaticSingleton getInstance(){
return SingletonDepth.instance;
}
}
6.双重校验锁
有一种情况,有俩个线程,线程A执行到了第一个if条件判断instance =null,A进入了锁定块;线程B也执行到了if条件判断instance = null,但是锁被A占用,A成功实例化后退出代码块后线程B才能进入,因为A已经实例化,退出代码块。
A获取到了单例实例并返回,线程B没有获取到单例并返回Null。
public class TwinCheckSingleton {
private static TwinCheckSingleton instance;
private TwinCheckSingleton(){
System.out.println("Singleton has loaded");
}
public static TwinCheckSingleton getInstance(){
if(instance==null){
synchronized (TwinCheckSingleton.class){
if(instance==null){
instance=new TwinCheckSingleton();
}
}
}
return instance;
}
}
7.枚举方法(线程安全)
创建枚举默认就是线程安全的,还能防止反序列化导致重新创建新的对象,是唯一一种不会被反射破坏单例状态的模式
public enum EnumSingleton{
// 定义一个枚举的元素。EnumSingleton
INSTANCE;
public void EnumSingletonDemo() {
// 功能处理
System.err.println("功能处理");
}
}
下一篇:简单工厂