博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
1.5(设计模式)单例模式
阅读量:5788 次
发布时间:2019-06-18

本文共 2536 字,大约阅读时间需要 8 分钟。

单例模式提供了创建一个类唯一对象的方式。

单例模式情况下,某一个类只有唯一实例,且该实例可以被其他所有对象引用。

 

单例模式的关键点:

1.构造器私有化

2.实例对象静态化

 

构造器私有化后,无法通过new来创建,只能通过该类提供的方法获取实例对象。

对象静态化后可保证全局有效,使获取的对象始终是一个对象。

 

单例模式的实现方法:

1、懒汉式(线程不安全、延时加载)

延时加载即在调用时才会加载。

//懒汉式,非同步  线程不安全//由于其非同步,所以严格意义上来说不属于单例模式//在多线程下无法正常工作。class Singleton{     private static Singleton singleton;    private Singleton() {}    public static Singleton getInstance() {        if(singleton == null) {            singleton = new Singleton();        }        return singleton;    }        public void printObject() {        System.out.println(this);    }}

这种单例模式不适用于多线程情况。

 

2、懒汉式(线程安全、延时加载)

//线程安全,可以在多线程中使用,但效率低下。////class Singleton{   // 懒汉式线程安全    private static Singleton singleton;    private Singleton() {}    public synchronized static Singleton getInstance() {        if(singleton == null) {            singleton = new Singleton();        }        return singleton;    }        public void printObject() {        System.out.println(this);    }}

这里通过synchronized关键字对其加锁,保证了在多线程情况下的安全,但是锁住整个方法效率较低。

 

3、饿汉式(线程安全,非延时加载)

即在初始化就完成加载,而不是在调用时完成加载。

//饿汉式//类在加载的时候就实例化了,就算thread1和thread2同时获取它,//取到的是类加载时实例化的那个变量的值,所以说是线程安全的。//饿汉式缺点是类加载是就初始化对象,浪费内存。class Singleton{    private static Singleton singleton = new Singleton();    private Singleton() {}    public static Singleton getInstance() {        return singleton;    }    public void printObject() {        System.out.println(this);    }    }

饿汉式在类加载时就创建了对象,避免了多线程访问的并发问题。

但其类加载时就需要实例化对象,消耗内存。

 

4、双重校验锁(线程安全,延时加载)

//双重校验锁//多线程下能保持高性能class Singleton{    private volatile static Singleton singleton;    private Singleton() {}    public static Singleton getInstance() {        if(singleton == null) {            synchronized(Singleton.class) {  //此时锁住的是类                if(singleton == null)                    singleton =  new Singleton();            }        }        return singleton;    }     public void printObject() {        System.out.println(this);    }}

 

采用双检锁既保证了多线程下的安全性,又保持了较好的性能。

因为当对象存在时,第一判空条件上没有添加synchronized,不会降低效率。

后续创建对象实例部分才添加了synchronized关键字锁住了类,然后再判断对象是否为空,保证了安全性。

 

5、登记式/静态内部类(线程安全、延时加载)

class Singleton{    private Singleton() {};    //静态内部类    private static class SingletonHolder{        private static final Singleton singleton = new Singleton();    }        public static Singleton getInstance() {        return SingletonHolder.singleton;    }        public void printObject() {        System.out.println(this);    }}

静态内部类加载后并不会立刻加载内部的静态属性,只有外部调用内部类才会初始化静态属性,加载实例。

这样既保证了多线程情况下的安全性,而且实现了延迟加载。

 

 

参考资料:

 

转载于:https://www.cnblogs.com/huang-changfan/p/10736902.html

你可能感兴趣的文章
App上架/更新怕被拒? iOS过审“避雷秘籍”请查收
查看>>
CentOS 7 防火墙操作
查看>>
关于 top 工具的 6 个替代方案
查看>>
程序员最讨厌的9句话,你可有补充?
查看>>
PAT A1037
查看>>
浅谈RPC
查看>>
HDU 4422 The Little Girl who Picks Mushrooms(简单题)
查看>>
HDUOJ---------(1045)Fire Net
查看>>
TextView 超链接点击跳转到下一个Activity
查看>>
sql server 2008安装的时候选NT AUTHORITY\NEWORK SERVICE 还是选 NT AUTHORITY\SYSTEM ?
查看>>
UNIX环境高级编程之第4章:文件和文件夹-习题
查看>>
bzoj2843极地旅行社题解
查看>>
【Linux】Linux中常用操作命令
查看>>
MyBatis3-SqlSessionDaoSupport的使用
查看>>
ReactiveSwift源码解析(三) Signal代码的基本实现
查看>>
MVC模式利用xib文件定制collectionCell
查看>>
(六)Oracle学习笔记—— 约束
查看>>
【SQL】查询数据库中某个字段有重复值出现的信息
查看>>
mysql 行转列 列转行
查看>>
[Oracle]如何在Oracle中设置Event
查看>>