文档章节

python 单例模式实现多线程共享连接池

鼎铭
 鼎铭
发布于 2017/09/02 23:42
字数 605
阅读 208
收藏 0

     我们经常使用数据库连接池,但那是有时候有些库并没有实现线程安全的连接池,这个时候,该如何自己封装?多进程和多线程甚至协程模式下,如何控制数据库连接数量或者是socket连接数。这个问题很有意义。

该文章后续仍在不断的更新修改中, 请移步到原文地址http://dmwan.cc

    首先,多进程,通常的做法是每个进程实例化一个连接池,为什么不共享一个池,因为多进程和多线程同步的开销不一样,一般三方库都不会支持,但是redis 的库可以,他有些细节不一样。然后多线程共享,只需要将连接放到一个线程安全的容器,比如list 或者queue中。注意多线程和多进程的queue实现方式完全不一样,多线程是使用的mmap。

    下面看看一个demo:

import multiprocessing
import threading
import os



def singleton(cls, *args, **kw):
    instances = {}#
    print "instance is",id(instances)
    def _singleton():
        #key = str(cls) + str(os.getpid())
        key = str(cls)
        if key not in instances:
            instances[key] = cls(*args, **kw)
        return instances[key]

    return _singleton
    print "instance has been free"

@singleton
class DB(object):
    def __init__(self):
        self.rabbitmq_pool = self.init_rabbitmq_pool()

    def init_rabbitmq_pool(self):
        pool = 1#为了简化
        return pool


#DB = singleton(DB)


def process1():
    print "proc 1 "
    db1 = DB()
    print "db1 is ", id(db1)


def process2():
    print "proc 2 "
    db2 = DB()
    print "db2 is", id(db2)

if __name__=="__main__":
    # print "multiproce "
    # pro1 = multiprocessing.Process(target=process1)
    # pro2 = multiprocessing.Process(target=process2)
    # pro1.start()
    # pro2.start()
    # pro1.join()
    # pro2.join()

    print "print thread"
    pro1 = threading.Thread(target=process1)
    pro2 = threading.Thread(target=process2)
    pro1.start()
    pro2.start()
    pro1.join()
    pro2.join()

这部分代码是简化了自己封装的连接池的代码, 主要观察线程单例是否生效,然后那个instance为什么线程能够共享一个连接池。

下面是打印结果:

instance is 140442806348048
print thread
proc 1 
db1 is  140442806366352proc 2 

db2 is 140442806366352

    看到结果,其实很多问题就知道答案了,使用装饰器后, 整个代码段加载的时候,装饰器就已经开始执行,这里的instances 是不会释放的,实际上代码初始化的时候就执行了DB = singleton(DB) ,相当于是 这个闭包是全局变量,又因为dict本身线程安全。所以每次线程用这闭包的时候,获取连接对象都是线程安全的。

    这里的单例对多进程是不会生效的。   

© 著作权归作者所有

共有 人打赏支持
鼎铭
粉丝 45
博文 68
码字总数 42542
作品 0
东城
程序员
Python学习:19.Python设计模式-单例模式

一、单例模式存在的意义   在这里的单例就是只有一个实例(这里的实例就像在面向对象的时候,创建了一个对象也可以说创建了一个实例),只用一个实例进行程序设计,首先我们可以了解一下什...

BD-ld-2017
07/31
0
0
《 Head First 》学习笔记:策略模式 (python实现)

学习<head first>,书中是用java 来实现,我用python比较多,所以在这里记下 用python实现的方法 。 书中策略模式的定义 : 策略模式 : 策略模式定义了算法族,分别封装起来,让它们之间可以...

Jbryan
2013/06/13
0
0
python 与设计模式 ——工厂与单例

python 与设计模式 源码地址:[http://git.oschina.net/duoduo3_69/python_design_pattern][1] git checkout v001(这个版本与此篇博客相符) zarkpy里面运用了很多设计模式,以前一直很费解p...

duoduo3_69
2013/11/27
0
0
Python新式类 new init 单例模式与作用域(四)

1 新式类与旧式类 新式类拥有经典类的全部特性之外,还有一些新的特性,比如 发生变化,新增了静态方法,python3目前都采用新式类,新式类是广度优先,旧式类是深度优先 (2)类的方法 静态方法 类方...

善良小郎君
06/18
0
0
大数据分析技术:Python面试之理解__new__和__init__的区别

很多同学都以为Python中的init是构造方法,但其实不然,Python中真正的构造方法是new。init和new有什么区别?本文就来探讨一下。 我们先来看一下init的用法 上面的代码会输出如下的结果 那么...

加米谷大数据
07/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
5
0
现场看路演了!

HiBlock
昨天
16
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
9
0
官方精简版Windows10:微软自己都看不过去了

微软宣布,该公司正在寻求解决方案,以减轻企业客户的Windows 10规模。该公司声称,企业客户下载整个Windows 10文件以更新设备既费钱又费时。 微软宣布,该公司正在寻求解决方案,以减轻企业...

linux-tao
昨天
19
0
TypeScript基础入门之JSX(二)

转发 TypeScript基础入门之JSX(二) 属性类型检查 键入检查属性的第一步是确定元素属性类型。 内在元素和基于价值的元素之间略有不同。 对于内部元素,它是JSX.IntrinsicElements上的属性类型...

durban
昨天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部