java设计模式-----4、单例模式

  单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的一个实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。

  其实,GoF对单例模式的定义是:保证一个类,只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。

  

  那么,我们为什么要用单例模式呢?

  这是因为在应用系统开发时,我们常常有以下需求:

  1、在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象。

  2、在整个程序空间使用全局变量,共享资源。

  3、在大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。

  因为单例模式可以保证为一个类只生成唯一的实例对象,所以这些情况,单例模式就派上用场了。

  单例模式分为几种情况

  1、饿汉式(在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快,同时无法做到延时加载)

public class Person {
    public static final Person person = new Person();

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

    //提供一个全局的静态方法
    public static Person getPerson(){
        return person;
    }
}

  

  2、接下来是懒汉式(在类加载时不初始化,可以延时加载)

     懒汉式可以分为两种,一种线程安全,一种线程不安全

  (1)懒汉式(线程不安全,但效率高)

public class Person {
    public static Person person = null;

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

    //提供一个全局的静态方法
    public static Person getPerson(){
        if(person == null){
            person = new Person();
        }
        return person;
    }
}

   (2)懒汉式(线程安全,但效率低)

 1 public class Person {
 2     public static Person person = null;
 3 
 4     //构造函数私有化
 5     private Person(){}
 6 
 7     //提供一个全局的静态方法
 8     public static synchronized Person getPerson(){
 9         if(person == null){
10             person = new Person();
11         }
12         return person;
13     }
14 }

   3、静态内部类(可以延时加载)

  这种方法是饿汉式的一种升级,这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,同时实现了延时加载

 1 public class Person {
 2     private static class PersonHolder{
 3         private static final Person person = new Person();
 4     }
 5 
 6     //构造函数私有化
 7     private Person(){}
 8 
 9     //提供一个全局的静态方法  
10     public static final Person getPerson(){
11         return PersonHolder.person;
12     }
13 }

  4、双重检查(对懒汉式的升级,效率更高)

public class Person {
    public static Person person = null;

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

    //提供一个全局的静态方法
    public static Person getPerson(){
        if(person == null){
            synchronized(Person.class){
                if(person == null){
                    person = new Person();
                }
            }
        }
        return person;
    }
}

  这样写,只把新建实例的代码放到同步锁中,为了保证线程安全再在同步锁中加一个判断,虽然看起来更繁琐,但是同步中的内容只会执行一次,执行过后,以后经过外层的if判断后,都不会在执行了,所以不会再有阻塞。程序运行的效率也会更加的高。

原文地址:https://www.cnblogs.com/xiaobai1226/p/8487696.html