亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 系統(tǒng) > Android > 正文

Android中單例模式的一些坑小結(jié)

2019-10-21 21:25:06
字體:
供稿:網(wǎng)友

前言

單例模式最初的定義出現(xiàn)于《設(shè)計(jì)模式》(艾迪生維斯理, 1994):“保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。”

而我對(duì)單例的理解是,在可控的范圍內(nèi)充當(dāng)全局變量的作用,就相當(dāng)于C語(yǔ)言中一個(gè)全局結(jié)構(gòu)體。

首先來看這樣一個(gè)單例,稍微有點(diǎn)經(jīng)驗(yàn)的同學(xué)可能都會(huì)說,這樣的單例是非線程安全的。要加個(gè)volatile關(guān)鍵字才可以。

 class Singleton{  private static Singleton singleton;  private Singleton(){};  public static Singleton getInstance()  {   if (singleton==null)   {    synchronized (Singleton.class)    {     if (singleton==null)     {      singleton=new Singleton();     }    }   }   return singleton;  } }

但是你要是問他,為什么是非線程安全的單例就答不出來了。搞清楚這個(gè)問題其實(shí) 對(duì)我們的多線程理解是很有好處的。
我們首先明確一下對(duì)于jvm來說,完成對(duì)一個(gè)變量的寫操作 到底是如何進(jìn)行的。

寫操作:

(1)先把值寫入cpu的高速緩存cache中。(2)然后再把這個(gè)cache中的值拷貝到ram(也就是我們的內(nèi)存)中。

注意啊,對(duì)于一個(gè)寫操作來說,這個(gè)(1)(2) 可不是原子操作,很有可能(1)執(zhí)行完畢以后,cpu又去干了其他事情,
并沒有第一時(shí)間把cache的值 寫入到ram中。而我們讀操作,都是從ram中去讀取一個(gè)值的。

所以這里我們可以想一下,如果是多線程場(chǎng)景的話,會(huì)有一些坑。

然后再說一個(gè)概念,對(duì)于 singleton=new Singleton(); 這一條語(yǔ)句來說,他顯然不是一條指令就可以完成的。

正常情況來說,我們要完成這條語(yǔ)句涉及到的指令大約如下:

1.申請(qǐng)一段堆內(nèi)存空間

2.在這個(gè)堆內(nèi)存空間中把我們需要的對(duì)象初始化完畢

3.把singleton這個(gè)引用指向我們的堆內(nèi)存空間地址。

但是坑爹就坑爹在,虛擬機(jī)會(huì)有一個(gè)指令重排序的概念。當(dāng)虛擬機(jī)發(fā)現(xiàn)單線程下 指令的順序變更不會(huì)導(dǎo)致結(jié)果異常的時(shí)候
就會(huì)觸發(fā)指令重排序的機(jī)制, 他會(huì)導(dǎo)致上述的 123順序發(fā)生變更,比如我們把順序改成132 你就會(huì)發(fā)現(xiàn) 結(jié)果還是一樣的。

(指令重排序的觸發(fā)機(jī)制準(zhǔn)確的來說是happens before原則 有興趣的同學(xué)可以深挖)

如果發(fā)生132的執(zhí)行順序 會(huì)發(fā)生什么?

假設(shè)線程a 進(jìn)入到了同步代碼塊中,這個(gè)時(shí)候觸發(fā)了指令重排序,順序變成132,假設(shè)cpu這個(gè)時(shí)候執(zhí)行了13。然后轉(zhuǎn)頭
去執(zhí)行線程b,線程b 進(jìn)入getInstance方法的時(shí)候,他發(fā)現(xiàn)singleton 不是null了,于是歡天喜地的return了,
但是要知道這個(gè)時(shí)候線程a的 2還沒執(zhí)行,也就是說singleton雖然不是空,但是他指向的地址空間里面啥都沒有,對(duì)象還沒有初始化。所以這是一個(gè)非常大的隱患,雖然他發(fā)生的概率極低,低到我現(xiàn)在都沒有復(fù)現(xiàn)過這種現(xiàn)象,但是依舊有概率。

那么正確的寫法:

  class Singleton{  private static volatile Singleton singleton;  private Singleton(){};  public static Singleton getInstance()  {   if (singleton==null)   {    synchronized (Singleton.class)    {     if (singleton==null)     {      singleton=new Singleton();     }    }   }   return singleton;  } }

有很多人就會(huì)說 volatile 這個(gè)關(guān)鍵字以后,singleton=new Singleton(); 就不會(huì)發(fā)生指令重排了,所以這么做是正確的。

現(xiàn)在明確的告訴你,上面這個(gè)觀點(diǎn)是錯(cuò)誤的

singleton=new Singleton();  這條語(yǔ)句背后的指令依舊有概率發(fā)生指令重排,只不過 volatile修飾過以后,在 這條語(yǔ)句背后的指令完全執(zhí)行完畢以前,對(duì)singleton這個(gè)引用的讀操作全部被屏蔽了。

也就是說 132的執(zhí)行順序依舊會(huì)發(fā)生,只不過 當(dāng)執(zhí)行完13 而2沒有執(zhí)行的時(shí)候,volatile修飾過的這個(gè)變量,所有對(duì)他的讀操作
都會(huì)暫時(shí)屏蔽,等待2操作執(zhí)行完以后,才會(huì)進(jìn)行讀操作。

這才是volatile關(guān)鍵字加上去以后的作用。

android很多代碼比如eventbus的單例就是用的上述寫法。

當(dāng)然了,上述寫法是典型的懶漢寫法,所謂懶漢你就理解成用的時(shí)候才實(shí)例化,不用的話不實(shí)例化。

但是如果你的需求是這個(gè)單例無(wú)論在什么情況下都會(huì)存在,你當(dāng)然可以寫成餓漢,餓漢的寫法更簡(jiǎn)單。

缺點(diǎn)就是他會(huì)一直占用內(nèi)存。餓漢寫法很多,我寫個(gè)最簡(jiǎn)單的:

 class Singleton {  //最簡(jiǎn)單的寫法就是這個(gè)了,直接public就行  public static final Singleton instance = new Singleton();  private Singleton() {  } }

單例序列化會(huì)破壞對(duì)象唯一性嗎?

答案是會(huì)的:

package com.wuyue.test;import java.io.*;/** * Created by 16040657 on 2019/2/12. */public class Test2 { public static void main(String args[]) {  Singleton s1 = Singleton.instance;  File f = new File("../test.txt");  try {   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));   oos.writeObject(s1);   oos.close();   ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));   Singleton s3 = (Singleton) ois.readObject();   System.out.println("s1==s3:" + (s1 == s3));  } catch (IOException e) {   e.printStackTrace();  } catch (ClassNotFoundException e) {   e.printStackTrace();  } } static class Singleton implements Serializable {  //最簡(jiǎn)單的寫法就是這個(gè)了,直接public就行  public static final Singleton instance = new Singleton();  private Singleton() {  }//  //這個(gè)方法就可以保證序列化和反序列化得到的對(duì)象是同一個(gè)了//  private Object readResolve() {//   return instance;//  } }}

代碼比較簡(jiǎn)單,大家可以測(cè)試一下,s1和s3就是2個(gè)不同的對(duì)象,但是如果把注釋掉的readResolve方法放開的話,你就會(huì)發(fā)現(xiàn)
這個(gè)問題解決了,序列化和反序列化是同一個(gè)對(duì)象了。

對(duì)外部公開提供的sdk的單例要注意些什么?

尤其是對(duì)于很多金融安全類的sdk來說,如果你這個(gè)里面有單例的話,涉及到安全性要盡可能的不被業(yè)務(wù)方hook,
其中尤其要注意的就是 有人可能會(huì)利用反射來new一個(gè)對(duì)象,破壞單例

解決這個(gè)問題也不難,

 private Singleton() {   //防止有人利用反射惡意修改   if (null != instance) {    throw new RuntimeException("dont construct more!");   }  }

項(xiàng)目中的單例太多,如何有效管理?

其實(shí)就拿map管理就可以了,android里面的 wms,ams 等等系統(tǒng)單例服務(wù)都是這樣的。你傳一個(gè)key進(jìn)去 返回一個(gè)單例給你。
這個(gè)真的很有用哦,特別是大型工程,可以有效管理單例,文檔輸出就簡(jiǎn)單許多。

 static class SingletonManager {  private static Map<String, Object> objectMap = new HashMap<>();  private SingletonManager() {  }  public static void registerService(String key, Object ins) {   if (!objectMap.containsKey(key)) {    objectMap.put(key, ins);   }  }  public static Object getService(String key) {   return objectMap.get(key);  } }

android中使用單例還要注意些什么?

最主要的就是盡量不要利用單例模式存儲(chǔ)傳遞數(shù)據(jù),因?yàn)閍pp掛在后臺(tái)的時(shí)候進(jìn)程會(huì)容易被殺掉,如果回到前臺(tái)再取這個(gè)單例里的數(shù)據(jù)很容易就取到個(gè)null,所以android中寫單例的原則就是:

原則上不允許用單例模式傳遞數(shù)據(jù),如果一定要這么做,請(qǐng)考慮數(shù)據(jù)恢復(fù)現(xiàn)場(chǎng)。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
天堂中文在线资源| 亚洲欧美日韩天堂| 国产高清久久久| 欧美中文字幕在线观看| 91美女视频网站| 久久伦理在线| 91热这里只有精品| 黄色动漫网站| 欧美日韩亚洲第一| 黄色小说在线播放| 欧美人成在线视频| 久久国产精品99久久久久久丝袜| 国产mv久久久| 国产尤物在线观看| 最新亚洲一区| 精品国产一区二区三区四区vr| 丰满熟女人妻一区二区三区| **欧美大码日韩| 亚洲精品一区中文字幕乱码| 国产成+人+综合+亚洲欧洲| 一区二区三区国产在线观看| 亚洲精品国产成人久久av盗摄| 超碰免费在线| 成人avav在线| 缴情综合网五月天| 欧美一区中文字幕| 欧美熟妇另类久久久久久不卡| 免费在线观看成年人视频| 国产精品青青在线观看爽香蕉| 日韩午夜中文字幕| 国产鲁鲁视频在线观看特色| 黄色在线免费观看网站| 久久久久久久久久久91| 日本不卡在线播放| 最新日韩精品| 欧美13videosex性极品| 手机在线播放av| 国产精品一区二区在线播放| 久久精品ww人人做人人爽| 成人免费视频网站在线看| 婷婷免费在线观看| 国产成人一区二区三区影院| 成人精品视频一区二区三区尤物| 免费成人在线网站| 亚洲国产精品久久久久婷婷884| 国产小视频免费在线网址| 免费看国产黄色片| 色欲久久久天天天综合网| 国产麻豆成人传媒免费观看| 在线播放av片| 久久97久久97精品免视看| xxxx国产视频| 国产免费麻豆视频| 一区二区三区激情视频| 国产一区二区三区黄视频| 国产偷窥老熟盗摄视频| 九九热精品在线| 中文字幕色一区二区| 牛人盗摄一区二区三区视频| 中文字幕电影一区| 中文永久免费观看| 国产欧美日韩专区| 色8久久精品久久久久久蜜| 不卡中文字幕av| 国产大学生自拍视频| 欧美国产综合在线| 麻豆最新免费在线视频| 天天干天天操av| 亚洲精品在线免费| 日韩欧美精品一区二区三区| 日韩欧美一二区| 天堂资源在线观看| 精品国产伦理网| 米奇精品一区二区三区在线观看| 亚洲精品鲁一鲁一区二区三区| 5g国产欧美日韩视频| 天天草夜夜草| 2019av中文字幕| 永久免费无码av网站在线观看| 久久综合久久综合久久| 日韩av手机在线免费观看| 久久精品国产www456c0m| 电影网一区二区| 欧美午夜精品一区二区蜜桃| 日韩视频在线一区| 国产成人禁片免费观看视频| 国产乱视频在线观看| 亚洲一区一卡| 小嫩苞一区二区三区| 国产免费一区二区三区最新不卡| 久久精品精品电影网| 国产一区二区在线播放视频| 国产精品成人无码专区| 国产一区二区三区天码| 成人av在线天堂| 丰满少妇又爽又紧又丰满69| 精品国产一二区| 国产午夜精品视频一区二区三区| 国产精品偷伦视频免费观看国产| 欧美福利一区| 男人的天堂av高清在线| 伦理一区二区三区| 天天爽夜夜爽一区二区三区| 欧美二区在线观看| 精品人伦一区二区三区| 在线看片国产福利你懂的| 国产精品7m凸凹视频分类| bl在线肉h视频大尺度| 极品少妇一区二区三区精品视频| 在线天堂一区av电影| 91视视频在线直接观看在线看网页在线看| 国产一区二区四区| 亚洲乱码国产乱码精品精的特点| 日韩欧美区一区二| 久久久www成人免费精品| 玛丽玛丽电影原版免费观看1977| 欧美精品一区在线发布| 久久久国产在线视频| 色天使久久综合网天天| 国产亚洲精品熟女国产成人| 欧美在线色图| 97超碰国产在线| aaaaa级少妇高潮大片免费看| 精品一区二区三区免费视频| 亚洲国产精品久久精品怡红院| 国产福利91精品一区| 天天操天天干天天舔| 国产日本欧美一区二区三区| 免费看欧美美女黄的网站| 少妇高潮一区二区三区| 国产精品美女黄网| 日韩精品视频在线观看一区二区三区| 国产免费裸体视频| 中文字幕日韩三级片| 午夜视频在线免费播放| 欧美性猛交xxxx乱大交hd| 三上悠亚国产精品一区二区三区| 日本成人福利| 成人有码在线播放| 国产成人精品三级麻豆| 国产精品久久久久久久免费软件| 九九热免费在线观看| 亚洲一区有码| 欧美熟妇一区二区| 99久久99久久精品国产片桃花| 欧美另类激情| 中文字幕二区三区| 91国内在线| 性欧美一区二区| 日本va欧美va精品| 一区二区三区欧美亚洲| 亚洲综合国产| 91老司机福利 在线| 日韩**中文字幕毛片| 日韩久久精品| 亚洲国产中文字幕在线视频综合| 精品无码人妻一区二区三区品| 日批在线观看视频| 黄色录像特级片| 综合激情成人伊人| 亚洲国产精品二十页| 中文精品在线| 黑人一区二区| 国产精品99精品无码视| 色综合久久久久久久久久久| 色999韩欧美国产综合俺来也| 91精品国产综合久久婷婷香蕉| 国产成人精品一区二| 福利一区二区三区视频在线观看| 久久黄色网页| 久久久久久九九| 一二三四视频免费观看在线看| 久久精品一区二区免费播放| 国产视频在线观看一区| 日本阿v视频在线观看| a级片在线免费观看| 熟妇人妻无乱码中文字幕真矢织江| 深爱激情五月婷婷| 日韩视频永久免费| 在线视频中文字幕一区二区| 韩国在线视频一区| 另类专区亚洲| 先锋影音男人站| 午夜影视一区二区三区| 综合在线视频| 欧洲成人一区二区三区| 久久久久久久无码| 亚洲日本欧美中文幕| 国产黄色av免费看| 久草网站在线观看| 亚洲美腿欧美偷拍| 波多野结衣午夜| 超碰福利在线观看| 视频区小说区图片区| 欧美影院视频| 在线不卡一区二区| 日本tube24xxxxx| 国产一级片久久| 亚洲夜间福利| 日本不卡一区视频| 亚洲在线一区二区三区| 在线欧美成人| 国产探花在线看| 青青一区二区三区| 大香一本蕉伊线亚洲网| 国产精品久久久久久久久搜平片| 国产日韩av在线播放| 欧美韩日一区| 99在线视频免费| 久久精品国产亚洲AV无码男同| 久久久久久福利| 韩国主播福利视频一区二区三区| 一本色道久久综合狠狠躁篇怎么玩| 女教师淫辱の教室蜜臀av软件| 精品不卡一区二区| 爱爱爱免费视频在线观看| 欧美日韩国产精品自在自线| 少妇特黄a一区二区三区| 亚洲精品成人三区| 99热99这里只有精品| 日韩你懂的在线播放| xxxx欧美| 无码 人妻 在线 视频| 91成人在线免费观看| 日本不卡中文字幕| 黑人と日本人の交わりビデオ| 天堂资源最新在线| 欧洲亚洲在线视频| 亚洲bt天天射| 精品国产一区二区三区久久久狼| 91国偷自产一区二区使用方法| 91深夜福利视频| 日韩二区三区四区| 日本黄色www| 成人美女视频在线看| 亚洲色精品三区二区一区| 国产精品一区在线观看| 日韩亚洲综合在线| 久久精品国产成人精品| 成人av在线天堂| 国产一级特黄aaa大片| 亚洲a视频在线观看| 自拍视频国产精品| 亚洲精品666| 伊人亚洲综合网| 婷婷国产在线| 全球av集中精品导航福利| aa免费在线观看| 国产又粗又猛又爽视频| 亚洲无码精品一区二区三区| 国产亚洲一区二区三区啪| 日本爱爱爱视频| 国产欧美日韩精品专区| 中文字幕在线中文字幕日亚韩一区| 色婷婷久久久综合中文字幕| 欧美精品久久一区二区| 中文在线аv在线| 日本久久伊人| av成人亚洲| 伊人久久综合视频| 日韩av一区二区三区| 国产欧美激情视频| 成人午夜影视| 日本黄色大片在线观看| 欧美一级专区免费大片| 久久久久久av无码免费网站下载| 日韩理论在线观看| 韩国免费在线视频| 日韩经典中文字幕在线观看| 欧美精品一区二区三区中文字幕| 国产在线观看中文字幕| 成a人片在线观看| 中文字幕一区二区三区四区不卡| 日本不卡一区在线| 亚洲一区亚洲二区| 92看片淫黄大片欧美看国产片| 看欧美ab黄色大片视频免费| 手机在线看福利| 国产成人精品一区二区三区在线| 欧美一区二区三区公司| 户外露出一区二区三区| 极品美鲍一区| 欧美人与性动交xxⅹxx| 2019日本中文字幕| 女教师高潮黄又色视频| а√天堂官网中文在线| 久久电影网站中文字幕| 99蜜桃臀久久久欧美精品网站| 免费久久网站| 亚洲精品日韩成人| 亚洲美女色视频| 成人三级毛片| 黄色大片中文字幕| 精一区二区三区| 91麻豆国产福利在线观看宅福利| 激情小说亚洲| 日韩精品免费一区二区夜夜嗨| heisi视频网在线观看| 国产精品91久久| 国产精品香蕉国产| 亚洲午夜激情网站| 亚洲福利视频免费观看| 无码少妇精品一区二区免费动态| 人人狠狠综合久久亚洲婷| 亚洲国产99| 久久国产香蕉视频| 99麻豆久久久国产精品免费优播| 天天干天天干天天干| 国产精品欧美一区二区三区奶水| 一区二区三区福利| 亚洲精品久久久久久动漫器材一区| 久久精品国产精品亚洲精品| 日韩精品视频在线观看网址| 884aa四虎影成人精品一区| 国产男小鲜肉同志免费| 交视频在线观看国产| 国产精品美女www爽爽爽视频| 欧美人妖巨大在线| 羞羞答答国产精品www一本| 一级一片免费播放| 国产视频手机在线观看| 亚洲免费观看高清完整版在线| 精品欧美日韩在线| 午夜精品一区二区三区在线观看| 欧美性潮喷xxxxx免费视频看| 樱桃视频免费看| 欧美阿v一级看视频| 欧美另类一区|