跳转至

python单例模式

python单例模式记录

1、单例模式的应用场景

资源共享:当多个对象需要共享同一个资源时,可以使用单例模式来管理该资源的访问。例如,数据库连接池、日志记录器等。

配置信息:当需要在应用程序中共享配置信息时,可以使用单例模式来保存和访问配置对象。这样可以确保配置信息的一致性和全局可访问性。

缓存管理:在需要缓存数据的场景中,可以使用单例模式来管理缓存对象。这样可以避免重复创建缓存对象,提高性能和资源利用率。

对话框或窗口管理:在图形用户界面(GUI)应用程序中,可以使用单例模式来管理对话框或窗口对象。这样可以确保只有一个实例对象存在,并且可以方便地进行访问和控制。

日志记录:在需要记录应用程序日志的场景中,可以使用单例模式来管理日志记录器对象。这样可以确保只有一个日志记录器实例,并且可以在整个应用程序中方便地使用。

2、当一个类定义被执行时,将发生以下步骤:

解析 MRO 条目 确定适当的元类 准备类命名空间 执行类主体 创建类对象 参考:https://docs.python.org/zh-cn/3.7/reference/datamodel.html#customizing-class-creation

3、new()

调用以创建一个 cls 类的新实例。

new() 是一个静态方法 (因为是特例所以你不需要显式地声明),它会将所请求实例所属的类作为第一个参数。其余的参数会被传递给对象构造器表达式 (对类的调用)。new() 的返回值应为新对象实例 (通常是 cls 的实例)。

如果 new() 返回一个 cls 的实例,则新实例的 init() 方法会在之后被执行,例如 init(self[, ...]),其中 self 为新实例,其余的参数与被传递给 new() 的相同。

如果 new() 未返回一个 cls 的实例,则新实例的 init() 方法就不会被执行。

4、init()

在实例 (通过 new()) 被创建之后,返回调用者之前调用。其参数与传递给类构造器表达式的参数相同。一个基类如果有 init() 方法,则其所派生的类如果也有 init() 方法,就必须显式地调用它以确保实例基类部分的正确初始化;例如: super().init([args...]).

因为对象是由 new() 和 init() 协作构造完成的 (由 new() 创建,并由 init() 定制),所以 init() 返回的值只能是 None,否则会在运行时引发 TypeError。

5、非线程安全的单例模式

非线程安全
import time


class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            time.sleep(1)
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

#instance1 = Singleton()
#instance2 = Singleton()

#print(instance1 is instance2)  # 输出: True

import threading
def create_singleton():
    instance = Singleton()
    print(instance)

threads = []
for _ in range(10):
    t = threading.Thread(target=create_singleton)
    threads.append(t)
    t.start()

for t in threads:
    t.join()


<__main__.Singleton object at 0x7f8269c91f60>
<__main__.Singleton object at 0x7f8269c91000>
<__main__.Singleton object at 0x7f8269c90df0>
<__main__.Singleton object at 0x7f8269c90be0>
<__main__.Singleton object at 0x7f8269c909d0>
<__main__.Singleton object at 0x7f8269c907c0>
<__main__.Singleton object at 0x7f8269c905b0>
<__main__.Singleton object at 0x7f8269c903a0>
<__main__.Singleton object at 0x7f8269c90190>
<__main__.Singleton object at 0x7f8269c91d20>

6、线程安全的单例模式

线程安全的
import threading

class Singleton:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        thread_id = threading.current_thread()
        if not cls._instance:
            print("我再等待着", thread_id)

            with cls._lock:
                print("我进来了",thread_id)
                if not cls._instance:
                    cls._instance = super().__new__(cls, *args, **kwargs)
        print("我直接返回了", thread_id)
        return cls._instance


def create_singleton():
    instance = Singleton()
    print(instance)

threads = []
for _ in range(10):
    t = threading.Thread(target=create_singleton)
    threads.append(t)
    t.start()

for t in threads:
    t.join()



我再等待着 <Thread(Thread-1 (create_singleton), started 139852282197760)>
我进来了 <Thread(Thread-1 (create_singleton), started 139852282197760)>
我直接返回了 <Thread(Thread-1 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-2 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-3 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-4 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-5 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-6 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-7 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-8 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-9 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>


我直接返回了 <Thread(Thread-10 (create_singleton), started 139852282197760)>
<__main__.Singleton object at 0x7f31e59b90c0>

7、参考

https://docs.python.org/zh-cn/3.7/library/threading.html#using-locks-conditions-and-semaphores-in-the-with-statement

https://docs.python.org/zh-cn/3.7/library/threading.html#lock-objects



觉得有用的老铁们可以"微信"赞助一杯82年的雪碧呦。
txtddd
本文阅读量  次

评论