1. 程式人生 > >Android 單例模式幾種實現方式及簡析

Android 單例模式幾種實現方式及簡析

一.定義:
確保某一個類只有一個例項,而且自行例項並向整個系統提供這個例項

二.使用場景:
避免產生過多的物件消耗過多的資源,或者某種型別的物件只應該有且只有一個。例如,建立一個物件需要消耗的資源過多,如訪問資料庫或者IO 資源。

三.實現單例模式的關鍵點:
1.私有化構造方法
2.通過靜態方法或列舉返回單例類物件
3.確保單例類的物件有且只有一個,尤其在多執行緒下
4.確保單例物件在反序列化時不會重新構建物件

四.實現方式

1.Double Check Lock(DCL)實現模式

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

那麼這裡為啥判空兩次呢?
第一次判空是為了避免不必要的同步,第二次判空則是為了在null的情況下建立例項。
分析:sInstance=new SingleInstance()語句並不是一個原子操作,程式碼會被編譯成多條編譯指令,這裡大致做了三件事情
(1)給SingleInstance的例項分配記憶體
(2)呼叫SingleInstance的構造方法SingleInstance(),初始化成員欄位
(3)將sInstance的物件指向分配的記憶體空間(此時sInstance就不是null了)

但是,由於java編譯器允許處理器亂序執行,以及jdk1.5之前的JMM(Java Memory Model)的Cache,暫存器到主存回寫順序的規定,上面的(2)(3)的順序是不確定的,也就是說執行順序可能是1-3-2,1-2-3,如果是前者,(3)執行完(2)還未執行,切換到B執行緒,這時候sInstance已經是非空的了,B這時候直接取走sInstance,使用的時候就會出錯,這就是DCL失效的原因。
jdk1.5之後,sun公司意識到這個問題,調整了JVM,具體化了volatile關鍵字,可以保證sInstance每次都是從主存中取。

2.靜態內部類單例模式:

public class SingleInstance{
    private SingleInstance(){}
    public static SingleInstance getInstance(){
        return SingleInstanceHolder.sInstance;
    }
    private static class SingleInstanceHolder{
        private static final SingleInstance sInstance=new SingleInstance();
    }
}

第一次載入SingleInstance 並不是初始化sInstance,只有在第一次呼叫getInstance方法才會導致sInstance的初始化,這種方式能確保執行緒安全,單例物件唯一性。

3.列舉型別

public enum SingleInstance{
    INSTANCE;
    public void doSomething(){`這裡寫程式碼片`

    }
}

執行緒安全,任何時候都是單一例項。
在上述的幾種實現方式中,在反序列化的情況下他們會出現重新建立物件。為什麼?
序列化可以將一個單例的例項物件寫到磁碟,然後在讀出來,從而有效的獲得一個例項。即使構造方法是私有的,反序列化仍可以通過一個特殊途徑建立一個新的例項,,相當於呼叫構造方法,反序列化提供了一個特別的鉤子函式,可以控制物件的反序列化。在上述的示例中,如果杜絕物件在反序列化時重新生成物件,必須加入readResolve函式。列舉則不會出現這種問題

public class SingleInstance implements Serializable
{
    private static final long serialVersionUID = 0L;

    private static volatile SingleInstance sInstance = null;

    private SingleInstance()
    {
    }

    public static SingleInstance getInstance()
    {
        if (sInstance == null)
        {
            synchronized (SingleInstance.class)
            {
                if (sInstance == null)
                {
                    sInstance = new SingleInstance();
                }
            }
        }
        return sInstance;
    }

    private Object readResolve() throws ObjectStreamException
    {
        return sInstance;
    }
}

三點注意:
1.單例中如果需要Context,最好傳入ApplicationContext,否則很容易發生記憶體洩漏。
2.可序列化的欄位型別不是Java內建模型,這個欄位也要實現Serializable.
3.如果你調整了可序列化類的內部結構,沒有修改serialVersionUID,就會丟擲異常,最好的方案是將serialVersionUID設定為0L,這樣即使改 了類的內部結構,不會丟擲異常,只是修改的欄位為0或者null。

四.使用容器類實現單例模式

public class SingleInstanceManager
{
    private static Map<String, Object> sObjectMap = new HashMap<>();

    private SingleInstanceManager()
    {
    }

    public static void registerService(String key, Object instance)
    {
        if (!sObjectMap.containsKey(key))
        {
            sObjectMap.put(key, instance);
        }
    }

    public static Object getService(String key)
    {
        return sObjectMap.get(key);
    }
}

相關推薦

Android 模式實現方式

一.定義: 確保某一個類只有一個例項,而且自行例項並向整個系統提供這個例項 二.使用場景: 避免產生過多的物件消耗過多的資源,或者某種型別的物件只應該有且只有一個。例如,建立一個物件需要消耗的資源過多,如訪問資料庫或者IO 資源。 三.實現單例模式的關鍵

模式實現方式

size ron jdk null singleton bsp 還要 一個 fin 1、餓漢式:靜態常量 特點:單例的實例被聲明成static和final變量了,在第一次加載類到內存中時就會初始化,所以會創建實例本身是線程安全的 public class Sin

Java模式實現方式

開始 名稱 常量 就是 多線程開發 靜態代碼塊 浪費 ack 多線程同步 在平時的工作、學員的學習以及面試過程中,單例模式作為一種常用的設計模式,會經常被面試官問到,甚至筆試會要求學員現場默寫,下面將會就單例模式的實現思路和幾種常見的實現方式進行簡單的分享。

高併發下最全執行緒安全的模式實現

為了節約系統資源,有時需要確保系統中某個類只有唯一一個例項,當這個唯一例項建立成功之後,我們無法再建立一個同類型的其他物件,所有的操作都只能基於這個唯一例項。 但是餓漢式單例類不能實現延遲載入,不管將來用不用始終佔據記憶體;懶漢式單例類執行緒安全控制煩瑣,而且效能受影響。可

模式6實現方式

一:餓漢式public class MyObject { // 立即載入方式==餓漢模式 private static MyObject myObject = new MyObject();

模式——六實現方式(懶漢、餓漢、雙重檢驗鎖、靜態內部類、列舉)

單例模式 單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不

c#模式實現方式

    //單例模式一,本模式具有多執行緒不安全性,可通過多執行緒鎖來實現功能     public class Class1     {         //(1)將建構函式定義為private         private Class1()         {  

Java 模式實現的差別

單例模式確保某個類只有一個例項,而且自行例項化並向整個系統提供這個例項。 思路是通過將該類的構造方法設為private,那麼在其他類中不能直接例項化該類。那麼為了得到該類的例項,需要有public的static方法來返回該類的例項。(之所以static是為了可以直接用

模式實現方式對比

所謂單例就是在系統中只有一個該類的例項。單例模式的核心分以下三個步驟: 構造方法私有化。即不能在類外例項化,只能在類內例項化。 在本類中建立本類的例項。 在本類中提供給外部獲取例項的方式。 單例模式的實現方式有兩種:餓漢模式和懶漢模式。 餓漢模式 不管現

模式寫法

遺憾 想象 develop 由於 tcl loader adr 希望 線程不安全 第一種(懶漢,線程不安全): Java代碼 public class Singleton { private static Singleton instance;

的三實現方式

In imp SQ span wrap 定制 bsp () import 一:類方法實現單例 class Mysql: __instance = None def __init__(self,host,port): self.ho

C++之智慧指標和普通指標模式實現

1  問題 實現c++的單例模式,這裡測試分別寫了通過智慧指標返回物件和普通返回指標     2  程式碼測試 include <iostream> #include <mutex> #include <m

的兩實現方式、多個版本利弊對照

        單例設計模式,顧明思議,只有一個例項,先交代重要一點,為防止外界對該類進行例項化,需要把類的建構函式宣告為私有的,這樣大家對原理理解更深入些。 1、餓漢式 餓漢模式單例程式碼,經典,可用,無需改進。 package com.sing

模式建立方式

在建立單例模式的時候,如果單純的只考慮單例而不思考那樣做的話會產生什麼問題這樣是不嚴謹的,比如會發生執行緒安全問題,看了一些文章其中一篇寫得非常詳細有關單例模式的問題和效能比較,這篇文章http://blog.sina.com.cn/s/blog_62c7c3030100zw

Android非同步機制的實現方式剖析

今天來談一談android中非同步處理機制,眾所周知在android中由於UI主執行緒是不安全的,因此不能直接在子執行緒中操作UI,一般我們會用到非同步機制來解決這種問題,下面會介紹兩種常用的非同步機制Thread+Handler與Async Task機制; 一、Thre

關於Android圓角ImageView的實現方式

在實際的開發中,我們經常會遇到需要圓角ImageView的情況,但是這種ImageView官方是沒有提供的,所以需要我們去自己重寫ImageView來達到圓角的效果,但是實現這種圓角效果其實有幾種不同的實現方式,所以這一篇就對不同的實現方式進行講解,並簡單分析。 一.BitmapShader方式 首先簡

python模式實現方法

1.方法1,程式執行過程中,某個類物件只有1個,該類物件的例項物件可以有無數個,根絕這點,讓類物件持有一個例項化物件,重寫類物件的__new__方法,始終返回持有的這個例項化物件,即可實現單例模式。 class Person1: _single = None

模式的多種實現方式

相對於第三種方式,這種方式是Singleton類被裝載了,instance不一定被初始化。因為SingletonHolder類沒有被主動使用,只有顯式通過呼叫getInstance方法時,才會顯式裝載SingletonHolder類,從而例項化instance。例如,如果例項化instance很消耗資源,我

模式6實現利弊分析

[TOC] # 單例模式6種實現及利弊分析 單例模式三要素 - **私有的構造方法;** - **指向自己例項的私有靜態引用;** - **以自己例項為返回值的靜態的公有方法** ## **1.餓漢式** ```java public class Singleton { private

求斐波那契數列第n位的實現方式效能對比(c#語言)

在每一種程式語言裡,斐波那契數列的計算方式都是一個經典的話題。它可能有很多種計算方式,例如:遞迴、迭代、數學公式。哪種演算法最容易理解,哪種演算法是效能最好的呢? 這裡給大家分享一下我對它的研究和總結:下面是幾種常見的程式碼實現方式,以及各自的優缺點、效能對比。 Iteration using Syst