单例,是JAVA 设计模式的一种,指的是一个类在全局中,JAVA中有不少情况是一个类不能产生太多实例的,由始至终都是只有一个对象的存在, 其中又分为懒汉式和饿汉式,什么是懒汉式呢? 就是你需要使用的时候,他才去实例化, 而饿汗式则为加载类的时候就已经实例化好一个对象了,下面贴上代码
懒汉式:
/**
*
*@Description: 懒汉式
*@Author: guanzhou.su
*@Date: 2019/8/25
**/
public class Singleton {
// 私有静态类
private static Singleton singleton;
// 无参构造函数私有化,避免外部new出来
private Singleton() {}
// 提供静态方法调用实例
public static Singleton instance() {
// 检测到空对象,实例化
if (singleton == null) {
System.out.println("实例化Singleton");
singleton = new Singleton();
} else {
System.out.println("Singleton已实例化");
}
return singleton;
}
public static void main(String[] args) {
Singleton s1 = Singleton.instance();
Singleton s2 = Singleton.instance();
System.out.println(s1 == s2);
}
}
运行 main 方法,得到以下控制台输出:
实例化Singleton
Singleton已实例化
true
下面贴上饿汗式单例代码:
/**
*
*@Description: 饿汉式
*@Author: guanzhou.su
*@Date: 2019/8/25
**/
public class Singleton {
// 私有静态类
private static Singleton singleton;
// 无参构造函数私有化,避免外部new出来
private Singleton() {}
static {
System.out.println("类加载就实例化对象");
singleton = new Singleton();
}
// 提供静态方法调用实例
public static Singleton instance() {
return singleton;
}
public static void main(String[] args) {
Singleton s1 = Singleton.instance();
Singleton s2 = Singleton.instance();
System.out.println(s1 == s2);
}
}
运行结果:
类加载就实例化对象
true
以上两个单例模式可以实现单例,但是在多线程模式下,会产生线程安全问题,为什么产生线程问题我就不敲内容了,偷了个懒复制了别人的内容
我们假设有多个线程1,线程2都需要使用这个单例对象。而恰巧,线程1在判断完s==null后突然交换了cpu的使用权,变为线程2执行,由于s仍然为null,那么线程2中就会创建这个Singleton的单例对象。之后线程1拿回cpu的使用权,而正好线程1之前暂停的位置就是判断s是否为null之后,创建对象之前。这样线程1又会创建一个新的Singleton对象
原文链接:https://blog.csdn.net/Mars_idea/article/details/80724404
所以,在多线程模式中,我们建议使用以下两种模式,
// 静态内部类模式
static inner class 线程安全饿汉模式单例
静态内部类, 比较经典的单例实现,兼容安全和性能
/**
*
*@Description: 静态内部类实现单例
*@Author: guanzhou.su
*@Date: 2019/8/25
**/
public class InnerSingleton {
private static class Singleton {
private static Singleton singleton = new Singleton();
}
public static Singleton getInstance() {
return Singleton.singleton;
}
}
dubble check instance 线程安全懒汉式单例
/**
*
*@Description: 线程安全懒汉式单例
*@Author: guanzhou.su
*@Date: 2019/8/25
**/
public class DubbleSingleton {
private static DubbleSingleton ds;
public static DubbleSingleton getDs(){
if(ds == null){
synchronized (DubbleSingleton.class) {
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
}
}