单例模式是一个类只有单个对象被创建
多例模式是一个类可以有多个对象被创建
下面展示单例模式的创建过程:
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author: admin
@file: 类方法.py
@time: 2021/05/24
@desc:
"""
class Custom():
def __init__(self, name):
import time
time.sleep(1)
self.name = name
# 通过类方法创建实例
@classmethod
def creat_class(cls, *args, **kwargs):
# 如果没有对象
if not hasattr(Custom, "_instance"):
Custom._instance = Custom(*args, **kwargs)
return Custom._instance
# # 通过类方法来创建类的实例化对象
c1 = Custom.creat_class('张三')
c2 = Custom.creat_class('李四')
print(c1)
print(c2)
print(c1 is c2) # True
<__main__.Custom object at 0x000002B8CD45F708>
<__main__.Custom object at 0x000002B8CD45F708>
True
但是,使用多线程时,使用类方法创建就会出现问题
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author: admin
@file: 类方法.py
@time: 2021/05/24
@desc:
"""
import threading
import time
class Custom():
def __init__(self, name):
import time
time.sleep(1)
self.name = name
# 通过类方法创建实例
@classmethod
def creat_class(cls, *args, **kwargs):
# 如果没有对象
if not hasattr(Custom, "_instance"):
Custom._instance = Custom(*args, **kwargs)
return Custom._instance
def task(arg):
obj = Custom.creat_class('柳杰')
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
<__main__.Custom object at 0x00000202CBD65148>
<__main__.Custom object at 0x00000202CBD62FC8>
<__main__.Custom object at 0x00000202CBD57048>
<__main__.Custom object at 0x00000202CBD62C08>
<__main__.Custom object at 0x00000202CBD62E88>
<__main__.Custom object at 0x00000202CBD62AC8>
<__main__.Custom object at 0x00000202CBD62988>
<__main__.Custom object at 0x00000202CBD62848>
<__main__.Custom object at 0x00000202CBD65288>
<__main__.Custom object at 0x00000202CBD62D48>
发现创建了不止一个对象!!!
解决办法:加锁!未加锁部分并发执行,加锁部分串行执行,速度降低,但是保证了数据安全
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author: admin
@file: 类方法.py
@time: 2021/05/24
@desc:
"""
import threading
import time
class Custom():
# 记录实例对象
_instance_lock = threading.Lock()
def __init__(self, name):
import time
time.sleep(1)
self.name = name
# 通过类方法创建实例
@classmethod
def creat_class(cls, *args, **kwargs):
# 如果没有对象
if not hasattr(Custom, "_instance"):
with Custom._instance_lock:
if not hasattr(Custom, "_instance"):
Custom._instance = Custom(*args, **kwargs)
return Custom._instance
def task(arg):
obj = Custom.creat_class('柳杰')
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
time.sleep(20)
# 前面已经创建了对象,它就是单例模式
obj = Custom.creat_class()
print('------')
print(obj)
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
<__main__.custom object at 0x000001C79ABE3208>
------
<__main__.custom object at 0x000001C79ABE3208>
def wer(func):
# 记录多个类的实例化对象
_instance = {
}
def inner(*args, **kwargs):
# 如果没有对象
if func not in _instance:
# 创建对象并将对象赋值给_instance
_instance[func] = func(*args, **kwargs)
return _instance[func]
return inner
@wer
class Myclass(object):
pass
m1 = Myclass()
m2 = Myclass()
print(m1)
print(m2)
print(m1 is m2) # True
<__main__.Myclass object at 0x0000017483B89C08>
<__main__.Myclass object at 0x0000017483B89C08>
True
当我们实现单例时,为了保证线程安全需要在内部加入锁。我们知道,当我们实例化一个对象时,是先执行了类的__new__方法实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以重写__new__方法,实现单例模式。
import threading
import time
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self):
time.sleep(1)
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = object.__new__(cls)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1, obj2)
def task(arg):
obj = Singleton()
print(obj)
for i in range(10):
t = threading.Thread(target=task, args=[i, ])
t.start()
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
<__main__.Singleton object at 0x0000026593A073C8>
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
## 平时我们使用的都是多例模式
class custom():
pass
c1 = custom()
c2 = custom()
print(c1)
print(c2)
# 我们可以通过他们的内存地址来判断是否是同一个实例也可以使用is判断
print(c1 is c2)
<__main__.custom object at 0x0000020C6AC28408>
<__main__.custom object at 0x0000020C6AC5CF48>
False
参考:
如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!