python多线程中只初始化⼀次的单例模式python中的单例可以利⽤__new__和__init__来实现。每次创建实例的时候总会获得同⼀个实例,但是每次也会执⾏__init__⽅法。这就会造成单例中的属性会被修改,更重要的是实例会被重新初始化。有时候我们并不希望再次初始化实例,我们希望直接获得已经创建好的实例。应⽤类变量和锁机制,可以实现需求。
⼀个简单的单例
import threading
from concurrent.futures.thread import ThreadPoolExecutor
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, num):
self.num = num
self.__init_flag = True
def get_name(self):
return self.num
def run_job(num):
obj = Singleton(num)
print("Thread:%s ID:%s NUM:%s" % (num, id(obj), obj.num))
with ThreadPoolExecutor(max_workers=5) as pool:
for line in range(10):
pool.submit(run_job, line)
上⾯样例的执⾏结果为。
Thread:0 ID:43341256 NUM:0
Thread:1 ID:43341256 NUM:1
Thread:2 ID:43341256 NUM:2
Thread:3 ID:43341256 NUM:3
Thread:4 ID:43341256 NUM:4
Thread:5 ID:43341256 NUM:5Thread:6 ID:43341256 NUM:6
Thread:7 ID:43341256 NUM:7
Thread:8 ID:43341256 NUM:8
Thread:9 ID:43341256 NUM:9
从结果中看到执⾏的10个线程中所创建的实例是同⼀个,因为实例的 id 是相同的,所以实例对象所指的内存地址是同⼀个,是同⼀个实例。但是它们的属性 num 是不同的,这是因为虽然实例是同⼀个,内存地址也是⼀个,但是每个实例都初始化了⼀遍(执⾏了⼀遍
__init__ ⽅法),初始化的时候对实例的属性 num 值进⾏了覆盖。
它们确确实实是同⼀个实例,但是属性值却发⽣了改变。这就像是“⼀个⼈”作为⼀个实例,⽽这个⼈改了名字,本来叫“⼩⼩”,后来改名叫“⼤⼤”,不管叫啥他都是同⼀个⼈。
只初始化⼀次的单例模式
有些时候我们创建⼀个单例后并不想让它修改属性。我们想第⼀次创建实例完成后,第⼆次创建的时候直接返回单例,不要在去执⾏初始化⽅法,避免多次初始化带来的资源和时间开销。样例代码如下所⽰。
import threading
from concurrent.futures.thread import ThreadPoolExecutor
class Singleton:
_lock_1 = threading.Lock()
_lock_2 = threading.Lock()
_instance = None
__init_flag = False
def __new__(cls, *args, **kwargs):
if cls._instance:
return cls._instance
with cls._lock_1:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, num):
if self.__init_flag:
return
with self._lock_2:
if self.__init_flag:
return
self.num = num
self.__init_flag = True
def get_name(self):
return self.num
def run_job(num):
obj = Singleton(num)
print("Thread:%s ID:%s NUM:%s" % (num, id(obj), obj.num))
with ThreadPoolExecutor(max_workers=10) as pool:
for line in range(50):
pool.submit(run_job, line)
# task = []
# for i in range(10):python单例模式
# t = threading.Thread(target=run_job, args=(i,))
# task.append(t)
#
# for one in task:
# one.start()
#
# for one in task:
# one.join()
执⾏结果为。
Thread:0 ID:43669064 NUM:0
Thread:1 ID:43669064 NUM:0
Thread:2 ID:43669064 NUM:0
Thread:3 ID:43669064 NUM:0
Thread:4 ID:43669064 NUM:0
Thread:5 ID:43669064 NUM:0
Thread:6 ID:43669064 NUM:0
Thread:7 ID:43669064 NUM:0Thread:8 ID:43669064 NUM:0 Thread:9 ID:43669064 NUM:0
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论