單例模式

目的: 單個進(jìn)程中只存在一個類的實(shí)例规伐,從而可以實(shí)現(xiàn)數(shù)據(jù)的共享虽惭,節(jié)省系統(tǒng)開銷枚荣,防止io阻塞等等

如何解決:判斷系統(tǒng)是否已有這個單例,如果有則返回,如果沒有就創(chuàng)建

但是在多進(jìn)程的應(yīng)用中灵再,單例模式就實(shí)現(xiàn)不了了,例如一些web應(yīng)用奴艾,django擦俐,這些,因?yàn)闀佣鄺l進(jìn)程來監(jiān)聽http請求握侧,這樣的會通過單例模式是實(shí)現(xiàn)不了數(shù)據(jù)共享的,也就是實(shí)現(xiàn)不了單例模式的目的了嘿期,這時需要用進(jìn)程間通信方法來實(shí)現(xiàn)數(shù)據(jù)共享品擎,當(dāng)然也可以嘗試使用redis這些數(shù)據(jù)庫實(shí)現(xiàn)數(shù)據(jù)共享,因?yàn)樗鼈兊淖x取數(shù)據(jù)較快备徐。

普通模式
class A(object):
    def __init__(self,name,male):
        self.name = name
        self.name = male

#實(shí)例化多個對象
obj1 = A('ben','boy')
obj2 = A('min','girl')
obj3 = A('miao','boy')
##打印內(nèi)存地址萄传,可以看到內(nèi)存地址都是不一樣的
print id(obj1),id(obj2),id(obj3)

單例模式有三種方法:

第一種方法:裝飾器方法

def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances: # 如果類沒有在 字典中
            instances[cls] = cls(*args, **kwargs)   # { 類名: 實(shí)例對象 }
        return instances[cls]
    return wrapper


@singleton
class Foo(object):
    def __init__(self,name):
        self.name = name


foo1 = Foo('a')
foo2 = Foo('b')
print id(foo1) 2794874519960
print id(foo2) 2794874519960

第二種方法 使用基類 注意此種方法不接受參數(shù)

class DiJi:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            cls._instance = super(DiJi, cls).__new__(cls, *args, **kwargs)
        return cls._instance

class Foo(DiJi): 
    pass

foo1 = Foo()
foo2 = Foo()
print id(foo1)
print id(foo2)

第三種方法: 使用元類

元類: 用于創(chuàng)建類的類,類對象創(chuàng)建實(shí)例對象時一定會調(diào)用 __call__方法,因此在調(diào)用 __call__時候保證始終創(chuàng)建一個實(shí)例即可,type是python中的一個元類

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance


class Foo(metaclass = Singleton):  不可修改

    def __init__(self,name):
        self.name = name

foo1 = Foo('s')
foo2 = Foo('a')

print(id(foo1))
print(id(foo2))
print (foo1 is foo2)
結(jié)果
  3128008950336
  3128008950336
  True

第四種方法: 使用模塊

模塊是天然的單例模式,因?yàn)槟K在第一次導(dǎo)入時,會生成 .pyc 文件蜜猾,當(dāng)?shù)诙螌?dǎo)入時秀菱,就會直接加載 .pyc 文件,而不會再次執(zhí)行模塊代碼蹭睡。因此衍菱,我們只需把相關(guān)的函數(shù)和數(shù)據(jù)定義在一個模塊中,就可以獲得一個單例對象了肩豁。

ce.py 在這個文件中

class Singleton(object):
    def __init__(self,name):
        self.name = name

在另一個文件中

import ce2
print(id(ce2.Singleton('a')))
print(id(ce2.Singleton('b')))
print(id(ce2.Singleton('a')) == id(ce2.Singleton('b')))
結(jié)果
  1912694489664
  1912694489664
  True

多線程中的單例模式

進(jìn)程: 系統(tǒng)進(jìn)行資源分配和調(diào)度的最小單位
線程: CPU調(diào)度和分派的最小單位
協(xié)程: 用戶控制的輕量級線程

加鎖脊串!未加鎖部分并發(fā)執(zhí)行,加鎖部分串行執(zhí)行,速度降低,但是保證了數(shù)據(jù)安全

import time
import os
import threading
class Singleton(object):
    _instance_lock = threading.Lock()    線程鎖

    def __init__(self,xxx):
        self.xxx = xxx
        time.sleep(1)

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):  返回對象是否具有具有給定名稱的屬性。這是通過調(diào)用getattr(obj清钥,name)
            with Singleton._instance_lock:    校驗(yàn)是否有線程鎖
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance


def task(arg):
    print(arg)
    obj = Singleton.instance(arg)
    print('子線程>>',obj)
    # print('父進(jìn)程PID',os.getppid())
    # print('當(dāng)前進(jìn)程PID:', os.getpid())

for i in range(10):
    t = threading.Thread(target=task,args=[i,]).start() # 開啟子線程

time.sleep(5)
obj = Singleton.instance()   '類調(diào)用類方法 和 對象調(diào)用實(shí)例方法相同 cls和self不用傳參,因?yàn)閏ls和self就代指的是類和對象,如果instance不是類方法,那就必須傳遞一個位置參數(shù) cls'
print('主進(jìn)程',obj)

結(jié)果
  數(shù)字就不列舉了
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  子線程>> <__main__.Singleton object at 0x000001737DDCB518>
  主進(jìn)程 <__main__.Singleton object at 0x000001737DDCB518>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琼锋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子祟昭,更是在濱河造成了極大的恐慌缕坎,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篡悟,死亡現(xiàn)場離奇詭異谜叹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恰力,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門叉谜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人踩萎,你說我怎么就攤上這事停局。” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵董栽,是天一觀的道長码倦。 經(jīng)常有香客問我,道長锭碳,這世上最難降的妖魔是什么袁稽? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮擒抛,結(jié)果婚禮上推汽,老公的妹妹穿的比我還像新娘。我一直安慰自己歧沪,他們只是感情好歹撒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诊胞,像睡著了一般暖夭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撵孤,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天迈着,我揣著相機(jī)與錄音,去河邊找鬼邪码。 笑死裕菠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闭专。 我是一名探鬼主播糕韧,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喻圃!你這毒婦竟也來了萤彩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斧拍,失蹤者是張志新(化名)和其女友劉穎雀扶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肆汹,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愚墓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了昂勉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浪册。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖岗照,靈堂內(nèi)的尸體忽然破棺而出村象,到底是詐尸還是另有隱情笆环,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布厚者,位于F島的核電站躁劣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏库菲。R本人自食惡果不足惜账忘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望熙宇。 院中可真熱鬧鳖擒,春花似錦、人聲如沸烫止。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烈拒。三九已至,卻和暖如春广鳍,著一層夾襖步出監(jiān)牢的瞬間荆几,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工赊时, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吨铸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓祖秒,卻偏偏與公主長得像诞吱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子竭缝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容