B2B网站_日本理论_B2B免费发布信息网站_日本看片网站_B2B企业贸易平台 -日本看片网站- 企资网

二維碼
企資網

掃一掃關注

當前位置: 首頁 » 企業資訊 » 資訊 » 正文

單例模式,關鍵字級別詳解

放大字體  縮小字體 發布日期:2021-09-01 05:50:36    作者:企資小編    瀏覽次數:123
導讀

大家好,我是課代表。歡迎關注我的公眾號_Java課代表,原創實戰干貨首發地兒,不要錯過呦!來,我們開始今天的分享!0.前言如果你去問一個寫過幾年代碼的程序員用過哪些設計模式,我打賭,90_以上的回答里面會帶【單

大家好,我是課代表。歡迎關注我的公眾號_Java課代表,原創實戰干貨首發地兒,不要錯過呦!

來,我們開始今天的分享!

0.前言

如果你去問一個寫過幾年代碼的程序員用過哪些設計模式,我打賭,90_以上的回答里面會帶【單例模式】。甚至有的面試官會直接問_說一下你用過哪些設計模式,單例就不用說了。你看,連面試官都聽煩了,火爆程度可見一斑。

不過,看似簡單的單例模式,里面蘊含了很多Java基礎,日常開發過程中課代表見過很多不規范的,甚至是有問題的單例實現。所以整理此文,總結一下單例模式的最佳實踐。

1、懶加載(懶漢)

所謂懶加載,就是直到第一次被調用時才加載。其實現需要考慮并發問題和指令重排,代碼如下_

public class Singleton {    private volatile static Singleton instance; //①    private Singleton() { //②    }    public static Singleton getInstance() {        if (instance __ null) {//③            synchronized (Singleton.class) {                if (instance __ null) {//④                    instance _ new Singleton();//⑤                }            }        }        return instance;    }}

這段代碼精簡至極,沒有一個字符是多余的,下面逐行解讀一下_

首先,注意到①處的volatile關鍵字,她具備兩項特性_

一是保證此變量對于所有線程的可見性。即當一條線程修改了這個變量的值,新值對于其他線程來說是可以立即得知的。

二是禁止指令重排序優化。

這里解釋一下指令重排序優化_

代碼 ⑤ 處的instance _ new Singleton();并不是原子的,大體可分為如下 3 步_

    分配內存調用構造函數初始化成實例
  1. instance指向分配的內存空間

JVM 允許在保證結果正確的前提下進行指令重排序優化。即如上 3 步可能的順序為1->2->3 或 1->3->2 。如果順序是 1->3->2 ,當 3 執行完,2 還未執行時,另一個線程執行到代碼 ③ 處,發現instance不為null,直接返回還未初始化好的instance并使用,就會報錯。

所以使用volatile,就是為了保證線程間的可見性和防止指令重排。

其次,代碼②處將構造函數聲明為private目的在于阻止使用new Singleton()這樣的代碼生成新實例。

最后,當客戶端調用Singleton.getInstance()時,先檢查是否已經實例化(代碼③),未實例化時同步代碼塊,然后再次檢查是否已實例化(代碼④),然后才執行代碼⑤。兩次檢查的意義在于,防止synchronized同步過程中其他線程進行了實例化。

這就是著名的雙重檢查鎖(Double check lock)實現單例,也即懶加載。

TIPS:

網上也有直接對getInstance()方法加鎖的版本,這樣大范圍的方法級別加鎖會導致并發變低,實際上第一次調用生成實例之后,后續獲取實例根本不需要并發控制了。而本例的雙重檢查鎖版本可以避免此并發問題。

2、預加載(餓漢)

與懶加載相對應,預加載是在類加載時就已經初始化好了,所以是天然線程安全的,代碼如下_

public class Singleton {    private static final Singleton instance _ new Singleton();// ①        private Singleton(){}        public static Singleton getInstance(){        return instance;    }}

注意到 ① 處的類變量使用了final

這里用final更多的意義在于提供語法約束。畢竟你是單例,就只有這一個實例,不可能再指向另一個。instance有了final的約束,后面再有人不小心編寫了修改其指向的代碼就會報語法錯誤。

這就好比@Override注解,你能保證寫對方法名和參數,那不寫注解也沒問題,但是有了注解的約束,編譯器就會幫你檢查,還能防止別人亂改。

3、靜態內部類

此方法和預加載原理相同,都是利用JVM類加載的特性實現天然的線程安全,不同之處在于,靜態內部類做到了延遲加載。

public class Singleton {        private static class SingletonHolder {        private static Singleton instance _ new Singleton();    }        private Singleton(){}    public static Singleton getInstance() {        return SingletonHolder.instance;    }}

SingletonHolder 是靜態內部類,當外部類Singleton被加載的時候并不會創建任何實例,只有當Singleton.getInstance()被調用的時候,才會創建Singleton實例,這一切由 JVM 天然完成,所以既保證了線程安全,又實現了延遲加載。

4、枚舉

沒錯,枚舉可以實現單例,而且這種方式是《Effective Java中文版》第二版 中的推薦實現方式。代碼極其簡單_

public enum Singleton {        INSTANCE;    public void doSomeThing(){        System.out.println("done");    }}

使用時直接Singleton.INSTANCE.doSomeThing();即可。

這里主要利用了枚舉的如下兩個特性_

枚舉的構造器總是私有的,所以不必像前幾種方式一樣顯式定義私有構造方法
  • 枚舉類中的每個值,都是實例(只有INSTANCE這一個實例)

    除此之外,枚舉還附帶了一些額外好處_無償地提供了序列化機制,還可以防止通過多次反序列化生成多個實例。

    鑒于此,單例的最佳實踐就是用枚舉來實現。

    5、總結

    事實上,單例的寫法并不止于本文所提的這 4 種,你可能還會看到很多其他變種,她們或多或少都存在一些缺陷,比如,懶加載方式將synchronized作用于整個方法上也能實現,但頻繁加鎖,釋放鎖會產生性能瓶頸,而完全去掉鎖又會帶來并發問題。

    所以,只要吃透了文中列出的這 4 種單例方式,就能做到舉一反三,見到別人寫的單例也能一眼看出對錯。

    文中所列的 4 種單例模式,除了枚舉之外,全都用到了static關鍵字,《Java 虛擬機規范》 規定,有幾種情況必須立即對類進行“初始化”,其中涉及static的場景如下_

    讀取或設置一個類型的靜態字段(被 final 修飾、已在編譯期把結果放入常量池的靜態字段除外)的時候。

    調用一個類型的靜態方法的時候。

    懶加載,預加載和靜態內部類正是利用了這兩點特性。

    static關鍵字遺忘的同學可以參看我的另一篇文章_《一題搞定static關鍵字》

    最后,再次強調一下,如果大家開發中需要手寫單例,建議聽從 Joshua Bloch在《Effective Java中文版》第二版 中的建議_

    單元素的枚舉類型已經成為實現 Singleton 的最佳方法

    參考資料_

    1、《Effective Java中文版》 Joshua Bloch 第二版 P15

    2、《深入理解 Java 虛擬機》 周志明 第3版,P444-P448,P264

    3、深入淺出單實例SINGLETON設計模式

    相關原創推薦

    一題搞定static關鍵字

  •  
    (文/企資小編)
    免責聲明
    本文僅代表作發布者:企資小編個人觀點,本站未對其內容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內容,一經發現,立即刪除,需自行承擔相應責任。涉及到版權或其他問題,請及時聯系我們刪除處理郵件:weilaitui@qq.com。
     

    Copyright ? 2016 - 2025 - 企資網 48903.COM All Rights Reserved 粵公網安備 44030702000589號

    粵ICP備16078936號

    微信

    關注
    微信

    微信二維碼

    WAP二維碼

    客服

    聯系
    客服

    聯系客服:

    在線QQ: 303377504

    客服電話: 020-82301567

    E_mail郵箱: weilaitui@qq.com

    微信公眾號: weishitui

    客服001 客服002 客服003

    工作時間:

    周一至周五: 09:00 - 18:00

    反饋

    用戶
    反饋

    主站蜘蛛池模板: 交通气象站_能见度检测仪_路面状况监测站- 天合环境科技 | 日本SMC气缸接头-速度控制阀-日本三菱伺服电机-苏州禾力自动化科技有限公司 | 政府园区专业委托招商平台_助力企业选址项目快速落地_东方龙商务集团 | 螺杆式冷水机-低温冷水机厂家-冷冻机-风冷式-水冷式冷水机-上海祝松机械有限公司 | 地图标注|微信高德百度地图标注|地图标记-做地图[ZuoMap.com] | 精密模具制造,注塑加工,吹塑和吹瓶加工,EPS泡沫包装生产 - 济南兴田塑胶有限公司 | 带锯机|木工带锯机圆木推台锯|跑车带锯机|河北茂业机械制造有限公司| | 工业CT-无锡璟能智能仪器有限公司 | 蓝牙音频分析仪-多功能-四通道-八通道音频分析仪-东莞市奥普新音频技术有限公司 | 天津拓展_天津团建_天津趣味运动会_天津活动策划公司-天津华天拓展培训中心 | 礼仪庆典公司,礼仪策划公司,庆典公司,演出公司,演艺公司,年会酒会,生日寿宴,动工仪式,开工仪式,奠基典礼,商务会议,竣工落成,乔迁揭牌,签约启动-东莞市开门红文化传媒有限公司 | 杜康白酒加盟_杜康酒代理_杜康酒招商加盟官网_杜康酒厂加盟总代理—杜康酒神全国运营中心 | 全自动包衣机-无菌分装隔离器-浙江迦南科技股份有限公司 | 缠膜机|缠绕包装机|无纺布包装机-济南达伦特机械设备有限公司 | 校园文化空间设计-数字化|中医文化空间设计-党建|法治廉政主题文化空间施工-山东锐尚文化传播公司 | 一体化净水器_一体化净水设备_一体化水处理设备-江苏旭浩鑫环保科技有限公司 | 液压油缸生产厂家-山东液压站-济南捷兴液压机电设备有限公司 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 工程管道/塑料管材/pvc排水管/ppr给水管/pe双壁波纹管等品牌管材批发厂家-河南洁尔康建材 | 步进驱动器「一体化」步进电机品牌厂家-一体式步进驱动 | 上海心叶港澳台联考一对一培训_上海心叶港澳台联考,港澳台联考一对一升学指导 | 慢回弹测试仪-落球回弹测试仪-北京冠测精电仪器设备有限公司 | 移动机器人产业联盟官网| 南昌旅行社_南昌国际旅行社_南昌国旅在线 | 电动液压篮球架_圆管地埋式篮球架_移动平箱篮球架-强森体育 | 上海小程序开发-小程序制作-上海小程序定制开发公司-微信商城小程序-上海咏熠 | 产业规划_产业园区规划-产业投资选址及规划招商托管一体化服务商-中机院产业园区规划网 | 小型手持气象站-空气负氧离子监测站-多要素微气象传感器-山东天合环境科技有限公司 | 酒糟烘干机-豆渣烘干机-薯渣烘干机-糟渣烘干设备厂家-焦作市真节能环保设备科技有限公司 | 2-羟基泽兰内酯-乙酰蒲公英萜醇-甘草查尔酮A-上海纯优生物科技有限公司 | 流水线电子称-钰恒-上下限报警电子秤-上海宿衡实业有限公司 | 有福网(yofus.com)洗照片冲印,毕业聚会纪念册相册制作个性DIY平台 | 上海电子秤厂家,电子秤厂家价格,上海吊秤厂家,吊秤供应价格-上海佳宜电子科技有限公司 | 扬尘监测_扬尘监测系统_带证扬尘监测设备 - 郑州港迪科技有限公司 | 恒压供水控制柜|无负压|一体化泵站控制柜|PLC远程调试|MCGS触摸屏|自动控制方案-联致自控设备 | 小型数控车床-数控车床厂家-双头数控车床 | 万博士范文网-您身边的范文参考网站Vanbs.com | 铝合金重力铸造_铝合金翻砂铸造_铝铸件厂家-东莞市铝得旺五金制品有限公司 | 泰来华顿液氮罐,美国MVE液氮罐,自增压液氮罐,定制液氮生物容器,进口杜瓦瓶-上海京灿精密机械有限公司 | 铝合金风口-玻璃钢轴流风机-玻璃钢屋顶风机-德州东润空调设备有限公司 | 内六角扳手「厂家」-温州市威豪五金工具有限公司 |