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>
View Code

 

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>
View Code

 

参考:

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

posted @ 2023-08-21 14:53  JvvYou  阅读(36)  评论(0编辑  收藏  举报