程序员人生 网站导航

四,单例模式

栏目:php教程时间:2016-11-03 08:08:48

1 单例模式

单例模式确保某个类只有1个实例,而且实例并向全部系统提供这个实例。

单例模式的3个特点:

  • 单例类只能有1个实例
  • 单例类必须要自行创建这个实例
  • 单例类需要向全部系统提供这个实例

单例模式中还存在着两种设计模式

  1. 饿汉式的单例模式
  2. 懒汉式的单例模式

2 饿汉式的单例模式

package com.designpattern.singleton;

/**
 * Created by Administrator on 2016/9/20.
 */
public class EagerSingleton {
    private static final EagerSingleton eagerSingleton = new EagerSingleton();

    private EagerSingleton(){

    }

    public static EagerSingleton getInstance(){
        return eagerSingleton;
    }

    public static void main(String args[]){
        EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();
        EagerSingleton eagerSingleton2 = EagerSingleton.getInstance();
        System.out.println(eagerSingleton1==eagerSingleton2);
    }
}

这类模式下线程是安全的,不会出现延迟加载而致使产生不同的实例对象。上面是采取静态常量的情势,代码也能够使用静态代码块的情势。静态代码块的情势以下:

package com.designpattern.singleton;

/**
 * Created by Administrator on 2016/9/20.
 */
public class EagerSingleton {
    private static final EagerSingleton eagerSingleton;

    static {
        eagerSingleton = new EagerSingleton();
    }

    private EagerSingleton(){

    }

    public static EagerSingleton getInstance(){
        return eagerSingleton;
    }

    public static void main(String args[]){
        EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();
        EagerSingleton eagerSingleton2 = EagerSingleton.getInstance();
        System.out.println(eagerSingleton1==eagerSingleton2);
    }
}

3 懒汉式的单例模式

懒汉式的单例模式是线程不安全的,如果在多线程下,1个线程进入了if (lazySingleton == null)判断语句块,还未来得及往下履行,另外一个线程也通过了这个判断语句,这时候便会产生多个实例。所以在多线程环境下不可以使用这类方式。

package com.designpattern.singleton;

/**
 * Created by Administrator on 2016/9/20.
 */
class LazySingleton {
    private static LazySingleton lazySingleton = null;

    private LazySingleton(){

    }
    public static LazySingleton getInstance(){
        if(lazySingleton == null){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}
class LazySigletonThread implements Runnable{

    @Override
    public void run() {
        System.out.println(LazySingleton.getInstance());
    }

    public static void main(String[] args) {
        LazySigletonThread lazySigletonThread1 = new LazySigletonThread();
        LazySigletonThread lazySigletonThread2 = new LazySigletonThread();
        Thread thread1 = new Thread(lazySigletonThread1);
        Thread thread2 = new Thread(lazySigletonThread2);
        thread1.start();
        thread2.start();
    }
}

履行结果会出现不同的实例对象,这样单例模式就失去存在的意义。

com.designpattern.singleton.LazySingleton@24189895
com.designpattern.singleton.LazySingleton@2e24a61e

但是如果在给getInstance()方法加上synchronized机制,这样就不会出现两个不同的实体类对象了。

    synchronized public static LazySingleton getInstance(){
        if(lazySingleton == null){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }

4 采取静态内部类的情势实现单例模式

public class Singleton {

    private Singleton() {}

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

这类方式跟饿汉式方式采取的机制类似,但又有不同。二者都是采取了类装载的机制来保证初始化实例时只有1个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时其实不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第1次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是没法进入的。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐