Python单例模式的代码实现和原理

Python单例设计模式的代码实现

python 复制代码
import threading
import time


class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance



class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()



class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)


if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()

这段代码实现并演示了Python中的单例模式,下面详细解释其代码实现和原理:

代码实现

单例类 Singleton 的定义:

python 复制代码
class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance
  • new 是Python类的一个特殊方法,用于创建并返回一个实例化对象。在单例模式里,它首先检查类属性 _instance 是否存在。如果不存在,就通过调用父类的 new 方法来创建一个新实例,并将其赋值给 _instance ;如果已经存在,直接返回这个已有的实例。
    Bus 类:
python 复制代码
class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()
  • Bus 类继承自 Singleton 类,也就继承了单例的特性。它定义了一个线程锁 lock ,用于在多线程环境下同步访问资源, sendData 方法用于发送数据,通过获取锁、模拟耗时操作、释放锁来保证线程安全。
    VisitEntity 线程类:
python 复制代码
class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)
  • VisitEntity 继承自 threading.Thread ,重写了 run 方法。在 run 方法中,它获取 Bus 类的单例实例,并调用其 sendData 方法发送数据,模拟多线程访问单例对象的场景。
    主程序部分:
python 复制代码
if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()
  • 在主程序中,创建了3个 VisitEntity 线程,为每个线程设置名字后启动它们,观察多线程环境下单例对象的运行情况。

原理

  • 单例模式的核心目标:确保一个类只有一个实例,并提供一个全局访问点。在这段代码里,利用 new 方法的特性,类第一次实例化时创建对象,后续实例化请求都返回这个已创建好的对象,以此保证整个程序生命周期内特定类的实例唯一性。
  • 线程安全性:由于多线程环境下,多个线程可能同时尝试创建实例,代码引入了线程锁( RLock )。在 Bus 类的 sendData 方法中,当线程访问共享资源(这里模拟发送数据的操作)时,先获取锁,操作完成后释放锁,防止数据竞争和不一致问题,保证单例模式在并发场景下正常工作。运行这段代码,会发现虽然有多个线程尝试访问 Bus 实例,但它们操作的是同一个实例,并且按顺序依次执行 sendData 方法。
相关推荐
woshihonghonga2 分钟前
Deepseek在它擅长的AI数据处理领域还有是有低级错误【k折交叉验证中每折样本数计算】
人工智能·python·深度学习·机器学习
程序猿20232 分钟前
Python每日一练---第六天:罗马数字转整数
开发语言·python·算法
程序员杰哥22 分钟前
Fiddler抓包手机和部分app无法连接网络问题
自动化测试·软件测试·python·测试工具·智能手机·fiddler·测试用例
weixin_3077791332 分钟前
用Python和FastAPI构建一个完整的企业级AI Agent微服务脚手架
python·fastapi·web app
熊猫_豆豆35 分钟前
回调函数的作用与举例(Python版)
服务器·python·编程语法
AI Echoes1 小时前
LangChain 使用语义路由选择不同的Prompt模板
人工智能·python·langchain·prompt·agent
JJJJ_iii1 小时前
【机器学习16】连续状态空间、深度Q网络DQN、经验回放、探索与利用
人工智能·笔记·python·机器学习·强化学习
CodeLongBear1 小时前
从Java后端到Python大模型:我的学习转型与规划
java·python·学习
ada7_1 小时前
LeetCode(python)——49.字母异位词分组
java·python·leetcode
我的xiaodoujiao1 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 23--数据驱动--参数化处理 Yaml 文件
python·学习·测试工具·pytest