国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

設(shè)計(jì)模式系列之單例模式

Jason / 3478人閱讀

摘要:下面我們來(lái)看看看中的單例模式,中使用的是單例注冊(cè)表的特殊方式實(shí)現(xiàn)的單例模式,所以說(shuō)模式是死的,需要靈活得運(yùn)用。

本文循序漸進(jìn)介紹單例模式的幾種實(shí)現(xiàn)方式,以及Jdk中使用到單例模式的例子,以及sring框架中使用到的單例模式例子。

餓漢式
package signgleton;

/**
 * 單例模式簡(jiǎn)單的實(shí)現(xiàn)
 */
public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {

    }
    public static Singleton getInstance() {
        return instance;
    }

}

”餓漢式“只是形象的比喻,因?yàn)樗胍@個(gè)實(shí)例的時(shí)候,不需要等待,別廢話,給哥拿來(lái)。通過(guò)static的初始化方式,借助類第一次被加載時(shí),就把Singleton實(shí)例給創(chuàng)建出來(lái)了,并存儲(chǔ)在JVM的方法區(qū),屬于類變量,被所有的實(shí)例共享。不同的線程調(diào)用都返回一個(gè)實(shí)例,所以這樣也保證了線程安全。

它還有個(gè)孿生兄弟,靜態(tài)代碼塊來(lái)實(shí)例化:

package signgleton;

/**
 * 通過(guò)靜態(tài)代碼塊創(chuàng)建實(shí)例對(duì)象
 */
public class StaticSignleton {

    private static StaticSignleton instance;

    /**
     * 靜態(tài)代碼塊創(chuàng)建實(shí)例
     */
    static {
       instance = new StaticSignleton();
    }
    
    private StaticSignleton() {

    }
    public static StaticSignleton getInstance() {
        return instance;
    }
}

科普一下類初始化順序:

靜態(tài)變量、靜態(tài)代碼塊初始化

構(gòu)造函數(shù)

自定義構(gòu)造函數(shù)

餓漢式缺點(diǎn):因?yàn)樵陬惐患虞d的時(shí)候?qū)ο缶蜁?huì)被實(shí)例化,這可能會(huì)造成不必要的消耗,如果你的程序不在乎這點(diǎn)消耗那就當(dāng)我沒(méi)說(shuō)。

下面介紹兩種方式解決上面的問(wèn)題:第一是使用靜態(tài)內(nèi)部類,第二是使用懶漢式

靜態(tài)內(nèi)部類
package signgleton;

/**
 * 使用靜態(tài)內(nèi)部類獲取單例實(shí)例
 */
public class StaticInnerClassSingleton {
    
    private static class InnerSingletonClass{
        private static final StaticInnerClassSingleton innerInstance = new StaticInnerClassSingleton();
        
    }
    private StaticInnerClassSingleton() {
        
    }
    public static final StaticInnerClassSingleton getStaticInstance() {
        return InnerSingletonClass.innerInstance;
    }
}

靜態(tài)內(nèi)部類同樣借助了JVM這個(gè)大佬來(lái)保證線程安全,只是他在類加載的時(shí)候并沒(méi)有立即實(shí)例化對(duì)象,而是采用了延遲加載策略,只有調(diào)用getStaticInstance的時(shí)候才用內(nèi)部類去創(chuàng)建實(shí)例

線程不安全的懶漢式
package signgleton;

/**
 * 線程不安全的懶漢式
 */
public class UnsafeSingleton {
    
    private static UnsafeSingleton unsafeSingleton;
    private UnsafeSingleton() {
        
    }
    public static UnsafeSingleton getUnsafeSingleton() {
        if (unsafeSingleton == null) {
            unsafeSingleton = new UnsafeSingleton();
        }
        return unsafeSingleton;
    }
    
}

雖然這樣寫達(dá)到了使用的時(shí)候才實(shí)例化的目的,但是也帶來(lái)的線程安全問(wèn)題。在多線程下,可能有兩個(gè)以上的線程同時(shí)進(jìn)入if(unsafeInstance == null),這樣會(huì)發(fā)生一些奇怪不定的結(jié)果。

線程安全的懶漢式
package signgleton;

/**
 * 線程安全的懶漢式
 */
public class SafeSingleton {
    private static SafeSingleton safeSingleton;
    private SafeSingleton() {

    }
    public static synchronized SafeSingleton getSafeSingleton() {
        if (safeSingleton == null) {
            safeSingleton = new SafeSingleton();
        }
        return safeSingleton;
    }
}

這種方式在方法上加synchronized同步關(guān)鍵字解決了餓漢式線程安全問(wèn)題,但是因?yàn)槊看握{(diào)用都加鎖,極大地降低了性能,因?yàn)橹挥械谝淮蝿?chuàng)建實(shí)例時(shí)需要加鎖,弄成現(xiàn)在每次都加鎖。有沒(méi)有解決辦法呢,當(dāng)然有,前輩們都是很聰明的,想出了雙重校驗(yàn)鎖這個(gè)經(jīng)典的例子.

雙重校驗(yàn)鎖
package signgleton;

/**
 * 線程不安全雙重校驗(yàn)鎖
 */
public class UnSafeTwoCheckSingleton {
    private static UnSafeTwoCheckSingleton singleton;
    private UnSafeTwoCheckSingleton() {
        
    }
    public static UnSafeTwoCheckSingleton getSingleton() {
        if (singleton == null) {
            synchronized (UnSafeTwoCheckSingleton.class) {
                if (singleton == null) {
                    singleton = new UnSafeTwoCheckSingleton();
                }
            }
        }
        return singleton;
    }
}

雙重校驗(yàn)鎖的形式主要是縮小了鎖的范圍,但是熟悉多線程編程的同學(xué)就可以看得出來(lái),即使這樣做還是有線程安全問(wèn)題,這里存在一個(gè)多個(gè)線程共享變量的可見(jiàn)性問(wèn)題(這部分我不太懂原理),解決方案就是使用volatile

使用volatile優(yōu)化

package signgleton;

/**
 * 線程安全雙重校驗(yàn)鎖
 */
public class SafeTwoCheckSingleton {
    private static volatile SafeTwoCheckSingleton singleton;
    private SafeTwoCheckSingleton() {
        
    }
    public static SafeTwoCheckSingleton getSingleton() {
        if (singleton == null) {
            synchronized (SafeTwoCheckSingleton.class) {
                if (singleton == null) {
                    singleton = new SafeTwoCheckSingleton();
                }
            }
        }
        return singleton;
    }
}

你以為這樣就安全了嗎,就想下班了嗎?還沒(méi)完,序列化這個(gè)惡棍會(huì)破壞單例,防范序列化這個(gè)惡棍破壞單例,可以在類中定義我們獲取實(shí)例的策略,既加readResolve。

防范序列化破壞單例
package signgleton;

import java.io.Serializable;

/**
 * 線程安全雙重校驗(yàn)鎖
 */
public class SafeTwoCheckSingleton implements Serializable{
    private static volatile SafeTwoCheckSingleton singleton;
    private SafeTwoCheckSingleton() {

    }
    public static SafeTwoCheckSingleton getSingleton() {
        if (singleton == null) {
            synchronized (SafeTwoCheckSingleton.class) {
                if (singleton == null) {
                    singleton = new SafeTwoCheckSingleton();
                }
            }
        }
        return singleton;
    }
    
    private Object readResolve() {
        return singleton;
    }
}

單例模式案例

這么多的實(shí)現(xiàn)方式,你會(huì)問(wèn),有什么用?用處可大了,下面講兩個(gè)使用實(shí)例,一個(gè)jdk的Runtime, 一個(gè)是Spring框架中的單例模式。

Runtime:是一個(gè)封裝了JVM進(jìn)程的類,每一個(gè)JAVA程序?qū)嶋H上都是JVM的一個(gè)進(jìn)程,每一個(gè)進(jìn)程都是對(duì)應(yīng)這么一個(gè)Runtime實(shí)例。
源碼如下:

public class Runtime {
        private static Runtime currentRuntime = new Runtime();


        public static Runtime getRuntime() {
            return currentRuntime;
        }
        private Runtime() {}
    }

這里使用了餓漢式單例模式。

下面我們來(lái)看看看spring 中的單例模式,spring中使用的是單例注冊(cè)表的特殊方式實(shí)現(xiàn)的單例模式,所以說(shuō)模式是死的,需要靈活得運(yùn)用。

看看單例注冊(cè)表的實(shí)現(xiàn)原理demo:

package signgleton;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 單例注冊(cè)表demo
 */
public class SingletonRegTest {

    private final static Map singletonObjects = new ConcurrentHashMap();

    /**
     * 類加載時(shí)初始化一個(gè)實(shí)例
     */
    static {
        SingletonRegTest singletonRegTest = new SingletonRegTest();
        singletonObjects.put(singletonRegTest.getClass().getName(), singletonRegTest);
    }

    public static SingletonRegTest getInstance(String name) {
        if (name == null) {
            // 默認(rèn)分配一個(gè)實(shí)例
            name = "signgleton.SingletonRegTest";
        }
        if (singletonObjects.get(name) == null) {
            try {
                // 將默認(rèn)實(shí)例放入緩存中
                singletonObjects.put(name, Class.forName(name).newInstance());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return (SingletonRegTest) singletonObjects.get(name);
    }
}

再來(lái)看看spring 源碼:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    @SuppressWarnings("unchecked")
    protected  T doGetBean(
            final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        final String beanName = transformedBeanName(name);
        Object bean;
        // 從單例注冊(cè)表中檢查是否存在單例緩存
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            ...
            // 返回緩存實(shí)例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        else {
            ...
            try {
                 ...

                // 如果是單例模式
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                ...
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                // 如果是原型模式
                else if (mbd.isPrototype()) {
                    ...
                }
                // 其他模式
                else {
                    ...
                }
            }
            catch (BeansException ex) {
               ...
            }
        }
        return (T) bean;
    }
}

我們進(jìn)入 getSingleton()方法:

import java.util.Map;

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    // 通過(guò) ConcurrentHashMap 實(shí)現(xiàn)單例注冊(cè)表
    private final Map singletonObjects = new ConcurrentHashMap(64);

    public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        Assert.notNull(beanName, ""beanName" must not be null");
        synchronized (this.singletonObjects) {
            // 檢查緩存中是否存在實(shí)例  
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                ...
                try {
                    singletonObject = singletonFactory.getObject();
                }
                catch (BeanCreationException ex) {
                    ...
                }
                finally {
                   ...
                }
                // 如果實(shí)例對(duì)象在不存在,我們注冊(cè)到單例注冊(cè)表中。
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

        }
    }
}

是不是和我們的單例注冊(cè)表demo很相似。
單例模式的講解后面隨著學(xué)習(xí)到其他框架再做相應(yīng)的補(bǔ)充,也歡迎大家獻(xiàn)言獻(xiàn)策。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/75033.html

相關(guān)文章

  • JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐系列單例模式

    摘要:本系列為設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐作者曾探學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版單例模式實(shí)現(xiàn)單例模式單例模式的定義是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。 本系列為《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》(作者:曾探)學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版 單例模式 實(shí)現(xiàn)單例模式 單例模式的定義是:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。單例模式是一種常用的模式...

    Airy 評(píng)論0 收藏0
  • 【php實(shí)現(xiàn)設(shè)計(jì)模式單例模式

    摘要:?jiǎn)卫J绞亲畛S茫彩亲詈?jiǎn)單的一種設(shè)計(jì)模式。什么是單例模式他是一個(gè)特殊的類,該類在系統(tǒng)運(yùn)行時(shí)只有一個(gè)實(shí)例。這個(gè)類必須提供一個(gè)獲取對(duì)象實(shí)例的方法。可以參考鳥(niǎo)哥的這遍文章,經(jīng)測(cè)試在下是有效的破壞單例 單例模式是最常用,也是最簡(jiǎn)單的一種設(shè)計(jì)模式。 什么是單例模式他是一個(gè)特殊的類,該類在系統(tǒng)運(yùn)行時(shí)只有一個(gè)實(shí)例。這個(gè)類必須提供一個(gè)獲取對(duì)象實(shí)例的方法。 有什么作用1.全局只創(chuàng)建一次實(shí)例,提高性能,...

    shery 評(píng)論0 收藏0
  • 大話PHP設(shè)計(jì)模式單例模式升級(jí)版

    摘要:用來(lái)指向已創(chuàng)建好的實(shí)例構(gòu)造函數(shù)為空注意這里是關(guān)鍵這是我們需要調(diào)用的方法把函數(shù)也定義為空,這樣就大功告成啦。 接上一篇大話PHP設(shè)計(jì)模式之單例模式 這一篇介紹一下升級(jí)版的單例模式,廢話不說(shuō)先上代碼 不完美的單例模式 class singleMode { //用來(lái)指向已創(chuàng)建好的實(shí)例 public static $instance; //判斷是...

    darcrand 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式單例模式

    摘要:博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。單例模式用途如果一個(gè)類負(fù)責(zé)連接數(shù)據(jù)庫(kù)的線程池日志記錄邏輯等等,此時(shí)需要單例模式來(lái)保證對(duì)象不被重復(fù)創(chuàng)建,以達(dá)到降低開(kāi)銷的目的。 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)...

    yy736044583 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式單例模式

    摘要:博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。單例模式用途如果一個(gè)類負(fù)責(zé)連接數(shù)據(jù)庫(kù)的線程池日志記錄邏輯等等,此時(shí)需要單例模式來(lái)保證對(duì)象不被重復(fù)創(chuàng)建,以達(dá)到降低開(kāi)銷的目的。 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)...

    lijy91 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<