大话设计模式之单例模式

参考—->程杰大神的《大话设计模式》—org
记一下一遍以后重复看时有新的理解,メモ

单例模式的UML图—>
这里写图片描述
饿汉模式:
静态初始化的方式就是指在自己被加载时就将自己实例化(一脸懵逼-_-)
详细代码—>

public class SingleTest {  
    private static SingleTest instance = new SingleTest();  

    private SingleTest(){  

    }  

    public SingleTest getInstance(){  
        return instance;  
    }  
}  

(脸上舒缓了点-_-)

懒汉模式:第一次被引用时才将自己实例化的。(又一脸懵逼-_-)

public class SingleTest {  

    private static SingleTest instance = null;  
    private SingleTest(){  

    }  
    public SingleTest getInstance(){  
        if(null == instance)  
            instance = new SingleTest();  
        return instance;  
    }  
}  

测试类


public class Test {

    public static void main(String[] args){

        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

        if(s1==s2){
            System.out.println("单例模式---构建成功");
        }

    //  MyRunnable myRunnable = new MyRunnable();
        // Thread ta = new Thread(myRunnable,"Thread-A");
    //   Thread tb = new Thread(myRunnable,"Thread-B");
        // ta.start();
    //   tb.start();
    }
}

(舒缓好多-_-)

当懒汉单例模式和多线程一起使用


public class MyRunnable implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Singleton sl = Singleton.getInstance();
        if(sl!=null){
            System.out.println(Thread.currentThread().getName() + " : "
                    + "当前Singleton对象的值= " + sl.toString());
        }
    }

}

测试类


public class Test {

    public static void main(String[] args){

//      Singleton s1 = Singleton.getInstance();
//      Singleton s2 = Singleton.getInstance();
//      
//      if(s1==s2){
//          System.out.println("单例模式---构建成功");
//      }

        MyRunnable myRunnable = new MyRunnable();
         Thread ta = new Thread(myRunnable,"Thread-A");
         Thread tb = new Thread(myRunnable,"Thread-B");
         ta.start();
         tb.start();
    }
}

1.不安全 当两个线程同时访问时还是会创建出两个不同的实例
解决方法加锁synchronized


public class Singleton {

    private static Singleton instance;

    /**
     * 构造函数私有化
     */
    private Singleton() {
    }

    public static Singleton getInstance() {
        //这样导致每次都会进行加锁
        synchronized (Singleton.class) {
            if (instance == null) {

                instance = new Singleton();
            }
        }

        return instance;

    }

}

测试类代码不变。

弊端,创建实例时每次都会加锁。
解决方式 双重锁定


public class Singleton {

    private static Singleton instance;
    /**
     * 构造函数私有化
     */
    private Singleton() {
    }

    public static Singleton getInstance() {

        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {

                    instance = new Singleton();
                }
            }
        }
        return instance;

    }

}

双重判断 分析–>当实例对象为空时并且同时两个A和B线程都调用了创建实例 的方法时,A线程判断第一个if为空时,此时cpu会切换到线程B去执行,B线程判断也为空,则进入锁机制 A 线程在等候,B线程 创建了实例后释放锁,第二个正在等候的 A 线程进入,如果没有第二重的判断,那么此时
A 线程也会创建一个实例这样就破坏了单例模式的目的。

故:控制台输出结果—>(虽然测试类中线程A先于线程B启动)
Thread-B : 当前Singleton对象的值= Singleton@14e672aa
Thread-A : 当前Singleton对象的值= Singleton@14e672aa
(还好还好,记录完思路更清晰了0_0。。。)

猜你喜欢

转载自blog.csdn.net/qq_15623599/article/details/77568183