单例模式

1.饿汉式

//饿汉式单例模式
//可能会浪费空间
public class HungryPattern {
//构造器私有
private HungryPattern() {}; private static final HungryPattern hungryPattern = new HungryPattern(); public HungryPattern getInstance() { return hungryPattern; } }

2.懒汉式

//懒汉式在单线程的情况下是OK的
public class LazyPattern {
    private LazyPattern() {
        System.out.println(Thread.currentThread().getName()+"OK!");//最后这边输出的可能不只一个线程。
    };
    
    private static LazyPattern lazyPattern;
    
    public static LazyPattern getInstance() {
        if(lazyPattern == null) {
            lazyPattern = new LazyPattern();             
        }
        return lazyPattern;
    }
//在多线程情况下会出现问题
    public static void main(String[] args) {
        for(int i = 0;i<=10;i++) {
            new Thread(()->{
                LazyPattern.getInstance();
            }).start();
        }
    }
}
结果:

Thread-0OK!
Thread-1OK!
Thread-2OK!

3.解决懒汉式的问题,双重检测锁模式

public class SynchronizedSingleton {
    private SynchronizedSingleton() {
        System.out.println(Thread.currentThread().getName()+"=> OK");
    }
    
    private static SynchronizedSingleton singleton;
    
    public static SynchronizedSingleton getInstance() {
        //双重检测锁模式
        if(singleton == null) {////这个判断是为了提高效率  如果没有这个判断 其它的线程来了就都得排队 有了这个判断 那么都不需要排队 直接返回回去
            synchronized(SynchronizedSingleton.class) {//锁的是类模板
                if(singleton == null) {
                    singleton = new SynchronizedSingleton();
                }
            }
        }
        return singleton;
    }
        
    public static void main(String[] args) {
        for(int i = 0;i<=10;i++) {
            new Thread(()->{
                SynchronizedSingleton.getInstance();
            }).start();
        }
    }
}

4.因为指令的重排,双重检测加锁的方式还是有可能出现问题,这个时候就需要加一个volatile.

package Singleton;

public class SynchronizedSingleton {
    private SynchronizedSingleton() {
        System.out.println(Thread.currentThread().getName()+"=> OK");
    }
    
    private static volatile SynchronizedSingleton singleton;
    
    public static SynchronizedSingleton getInstance() {
        //双重判断加锁
        if(singleton == null) {
            synchronized(SynchronizedSingleton.class) {
                if(singleton == null) {
                    singleton = new SynchronizedSingleton();//不是一个原子性操作
                    /*1.分配内存空间
                     *2.执行构造方法,初始化对象
                     *3.把这个对象指向这个空间
                     *正常的执行顺序是123
                     *但是由于指令重排:可能编程132
                     *这个时候有可能还没有完成实例化,但是另外一个线程过来了就会返回一个null
                     *
                     *这个时候就需要对singleton对象加一个volatile 来保证指令的不重排。
                     */
                }
            }
        }
        return singleton;
    }
        
    public static void main(String[] args) {
        for(int i = 0;i<=10;i++) {
            new Thread(()->{
                SynchronizedSingleton.getInstance();
            }).start();
        }

    }
}

 5.使用静态内部类方式:

public class Outer {
    private Outer() {
        
    }
    public static Outer getInstance() {
        return InnerClass.OUTER;
    }
    
    public static class InnerClass{
        private static final Outer OUTER = new Outer();
    }
}

 

 

posted @ 2020-11-20 11:18  Joyce502  阅读(77)  评论(0)    收藏  举报