单例模式是日常应用中最广泛的模式了,其目的就是令到单个进程中只存在一个类的实例,从而可以实现数据的共享,节省系统开销,防止io阻塞等等
但是在多进程的应用中,单例模式就实现不了了,例如一些web应用,django,这些,因为会启动多条进程来监听http请求,这样的会通过单例模式是实现不了数据共享的,也就是实现不了单例模式的目的了,这时需要用进程间通信方法来实现数据共享,当然也可以尝试使用redis这些nosql数据库实现数据共享,因为它们的读取数据较快。
#encoding=utf-8 __author__ = 'kevinlu1010@qq.com' class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls,'_the_instance'): cls._the_instance=object.__new__(cls,*args, **kwargs) return cls._the_instance class A(Singleton): print 'init before' def __init__(self): print 'i am __init__' def f(self): print 'i am f' a=A() b=A() a.f() print 'done'
这里写了个Singleton的类,通过重新__new__方法,可以查找当前进程有没有该类的实例,如果有就返回该实例,如果没有就新建一个
实例化两次A类(实际只实例化了一次)'init before'只会print一次,但是'i am __init__'是会print两次的,所以不想重复执行的代码要放在’init before‘的位置
这种实现方法有三个问题
1.并发的时候会有问题,这个可以通过在__new__中价格锁了解决
2.如果子类需要重新__new__函数,那就麻烦了
3.__init__函数会被调用多次
由于模块是线程安全的,而且一个模块只会被实例化一次,所以可以通过模块来实现单例
singleton.py
# encoding=utf-8 __author__ = 'kevinlu1010@qq.com' num = 0 def print_num(): print num
main.py
# encoding=utf-8 __author__ = 'kevinlu1010@qq.com' import singleton print singleton.num singleton.num += 1 singleton.print_num()
如果这样没有类的特性,可以这样:
singleton.py
# encoding=utf-8 __author__ = 'kevinlu1010@qq.com' class A(): print 'init before' num = 0 def __init__(self): print 'i am __init__' def f(self): print 'i am f' a=A()
main.py
# encoding=utf-8 __author__ = 'kevinlu1010@qq.com' import singleton a=singleton.a print a.f()