单例模式

1.定义

         单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式,单例模式又可以分为懒汉单例模式和恶汉单例模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

单例模式有 3 个特点:

  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点;

2.单例模式的结构与实现

        单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。

3.实现

   3.1懒汉模式

        需要的时候才创建

public class Singleton {

    private static Singleton singleton=null;

    public static synchronized Singleton install(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }
    public void SayHello(){
        System.out.println("创建成功");
    }
}

   3.2恶汉模式

    预先创建好,可以避免加锁造成的资源浪费

public class Singleton {

    private static Singleton singleton=new Singleton();

    public static Singleton install(){
        return singleton;
    }
    public void SayHello(){
        System.out.println("创建成功");
    }
}

3.3双重加锁模式

      加锁的懒汉模式看起来即解决了线程并发问题,又实现了延迟加载,然而它存在着性能问题,依然不够完美。synchronized修饰的同步方法比一般方法要慢很多,如果多次调用getInstance(),累积的性能损耗就比较大了。因此就有了双重校验锁,如下所示:

public class Singleton {

    private static volatile  Singleton singleton=null;

    public static Singleton install(){
        if(singleton==null){
            synchronized (Singleton.class){
                if(singleton==null){
                    singleton=new Singleton();
                }
            }
        }
        return singleton;
    }
    public void SayHello(){
        System.out.println("创建成功");
    }
}

   Volatile关键字解决了由于指令重排优化的存在,导致初始化Singleton和将对象地址赋给instance字段的顺序是不确定的。在某个线程创建单例对象时,在构造方法被调用之前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化。若紧接着另外一个线程来调用getInstance,取到的就是状态不正确的对象,程序就会出错的问题。volatile的一个语义是禁止指令重排序优化,也就保证了instance变量被赋值的时候对象已经是初始化过的,从而避免了上面说到的问题。

4.多例模式

    多例模式可以算作是单例模式的扩展,多例模式是说类的实例有多个,但是又不是无限多个,比如Java中的线程池,指定线程池的大小就是指定了可运行实例的大小。如下代码简单的展示了多例模式的简单使用:

public class Test {

    List<Person> personList=new ArrayList<>();

    int personNumber;

    int index=0;

    Test(int personNumber){
        this.personNumber=personNumber;
    }
    public  static  Test init(int personNumber){
        Test test=new Test(personNumber);
        return test;
    }

    public Person getPerson(){
        if(index>=personNumber){
            index=index%personNumber;
        }
        if(personList.size()<personNumber){
            Person person=new Person();
            person.setName(""+index);
            personList.add(person);
            index++;
            return person;
        }
        return personList.get(index++);
    }

    public static void main(String[] args) {
        //创建一个有2个容量的池子
        Test test=Test.init(2);
        for(int i=0;i<4;i++){
            System.out.println(test.getPerson().getName()+"正在干活");
        }
    }
}
//多例模式创建的对象
public class Person {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值