懒汉式双重检查方式
class LazySingletonTest {
private static volatile LazySingletonTest lazySingletonTest;
private LazySingletonTest() {
}
public static LazySingletonTest getInstance() {
if (lazySingletonTest == null) {
synchronized (LazySingletonTest.class) {
if (lazySingletonTest == null)
lazySingletonTest = new LazySingletonTest();
}
}
return lazySingletonTest;
}
}
这种方式是通过双重检查+synchronized实现线程安全。
volatile:防止jvm指令重排
如果没有加volatile,那么当线程1在进行实例化时,线程2刚好执行到第一层if时,发现实例不为null,但是实例并没有真正初始化完成,那么就会出现空指针。
懒汉式静态内部类方式
class LazySingletonTest2{
static class InnerClass{
private static LazySingletonTest2 lazySingletonTest2 = new LazySingletonTest2();
}
private LazySingletonTest2(){}
public static LazySingletonTest2 getInstance(){
return InnerClass.lazySingletonTest2;
}
}
这种方式是借助jvm类加载机制保证线程安全。但是如果通过反射获取该类的构造,通过构造获取对象,再通过静态方法获取对象,则会出现多个实例,不过也很好解决,在构造方法中加一层判断即可。
class LazySingletonTest2{
static class InnerClass{
private static LazySingletonTest2 lazySingletonTest2 = new LazySingletonTest2();
}
private LazySingletonTest2(){
if (InnerClass.lazySingletonTest2 != null)
throw new RuntimeException("不允许创建多个实例");
}
public static LazySingletonTest2 getInstance(){
return InnerClass.lazySingletonTest2;
}
}
饿汉式:
/**
*这种方式最简单
* 饿汉式1:这种方式是在类加载时,就创建了对象,如果你没有使用到这个对象可能造成内存浪费。
*/
public class SingletonTest1 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance==instance2);
}
}
class Singleton{
private Singleton(){}//私有构造防止new
private final static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
class Singleton1{
private Singleton1(){}//私有构造防止new
private static Singleton1 instance;
static {
instance = new Singleton1();
}
public static Singleton1 getInstance(){
return instance;
}
}
//和上面一模一样,不过是放在静态代码块实例化而已
枚举实现单例:
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanContainer {
public BeanContainer getInstance() {
return BeanContainerHolder.Holder.instance;
}
private enum BeanContainerHolder{
/**
* 存放单例实例
*/
Holder;
private BeanContainer instance;
BeanContainerHolder() {
this.instance = new BeanContainer();
}
}
}
Java源码中的单例模式
image.png
网友评论