python中實現可繼承的線程安全的單例模式

使用繼承並利用__new__

代碼實例

import threading
from time import sleep


class SingletonSample(object):
    _instanceLock = threading.Lock()
    _instance = {}

    def __new__(cls, *args, **kwargs):
        if cls not in cls._instance:
            print("get here 1")
            with cls._instanceLock:
                if cls not in cls._instance:
                    print("get here 2")
                    cls._instance[cls] = super(SingletonSample, cls).__new__(cls, *args)
                    print cls._instance
        return cls._instance[cls]


class SingletonSubA(SingletonSample):
    pass


class SingletonSubB(SingletonSample):
    pass


def task(index, obj, lock):
    if obj == "A":
        so = SingletonSubA()
    else:
        so = SingletonSubB()
    sleep(2)
    with lock:
        print("In Thread %s-%s" % (obj, index), so)

if __name__ == "__main__":
    
    print_lock = threading.Lock()

    try:
        error_so = SingletonSample()

        for i in range(10):
            thread = threading.Thread(target=task, name="thread-%d" % i, args=(i, "A", print_lock))
            thread.start()

        for i in range(10):
            thread = threading.Thread(target=task, name="thread-%d" % i, args=(i, "B", print_lock))
            thread.start()

    except Exception as e:
        print("ERROR, exception caught!Detail is: %s" % e)

 

執行一下:

C:\Python27\python.exe D:/代碼/python-DP/SingletonSample.py
get here 1
get here 2
{<class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>}
get here 1
get here 2
{<class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>, <class '__main__.SingletonSubA'>: <__main__.SingletonSubA object at 0x03377990>}
get here 1
get here 2
{<class '__main__.SingletonSubB'>: <__main__.SingletonSubB object at 0x033A8250>, <class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>, <class '__main__.SingletonSubA'>: <__main__.SingletonSubA object at 0x03377990>}
('In Thread A-2', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-0', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-1', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-4', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-5', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-3', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-7', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-6', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-9', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-8', <__main__.SingletonSubA object at 0x03377990>)
('In Thread B-0', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-1', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-2', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-3', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-4', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-5', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-6', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-8', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-9', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-7', <__main__.SingletonSubB object at 0x033A8250>)

Process finished with exit code 0

使用元類metaclass以及__call__

 

import threading
import time


class MetaSingleton(type):
    _instance = {}
    lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not cls._instance. has_key(cls):
            print("Get here 1!")
            with cls.lock:
                if not cls._instance. has_key(cls):
                    print("Get here 2!")
                    cls._instance[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
                    print(cls._instance)
        return cls._instance[cls]


class ConcreteSingleA(object):
    __metaclass__ = MetaSingleton

    def __init__(self, arg1, arg2):
        print("Now enter  in class ConcreteSingleA func __init__ ,arg1 is %s, arg2 is %s" % (arg1, arg2))
        self.arg1 = arg1
        self.arg2 = arg2
        print("In __init__ arg1 is %s" % self.arg1)
        print("In __init__ arg2 is %s" % self.arg2)


def task(arg1, arg2, lock_o):

    so = ConcreteSingleA(arg1, arg2)

    time.sleep(2)
    with lock_o:
        print so
        print("In thread %s arg1 is %s" % (arg1, arg1))
        print("In thread %s arg2 is %s" % (arg1, arg2))


if __name__ == "__main__":

    print_lock = threading.Lock()

    for i in range(0, 10):
        thread = threading.Thread(target=task, name="Thread%d" % i, args=(str(i), "aa%s"%i, print_lock))
        thread.start()

執行一下

C:\Python27\python.exe D:/代碼/python-DP/MetaClassSingletonSample.py
Get here 1!
Get here 2!
Now enter  in class ConcreteSingleA func __init__ ,arg1 is 0, arg2 is aa0
In __init__ arg1 is 0
In __init__ arg2 is aa0Get here 1!

{<class '__main__.ConcreteSingleA'>: <__main__.ConcreteSingleA object at 0x033989B0>}
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 3 arg1 is 3
In thread 3 arg2 is aa3
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 2 arg1 is 2
In thread 2 arg2 is aa2
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 0 arg1 is 0
In thread 0 arg2 is aa0
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 1 arg1 is 1
In thread 1 arg2 is aa1
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 6 arg1 is 6
In thread 6 arg2 is aa6
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 5 arg1 is 5
In thread 5 arg2 is aa5
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 4 arg1 is 4
In thread 4 arg2 is aa4
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 8 arg1 is 8
In thread 8 arg2 is aa8
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 9 arg1 is 9
In thread 9 arg2 is aa9
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 7 arg1 is 7
In thread 7 arg2 is aa7

Process finished with exit code 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章