Python自定义线程池实现方法分析


Posted in Python onFebruary 07, 2018

本文实例讲述了Python自定义线程池实现方法。分享给大家供大家参考,具体如下:

关于python的多线程,由与GIL的存在被广大群主所诟病,说python的多线程不是真正的多线程。但多线程处理IO密集的任务效率还是可以杠杠的。

我实现的这个线程池其实是根据银角的思路来实现的。

主要思路:

任务获取和执行:

1、任务加入队列,等待线程来获取并执行。
2、按需生成线程,每个线程循环取任务。

线程销毁:

1、获取任务是终止符时,线程停止。
2、线程池close()时,向任务队列加入和已生成线程等量的终止符。
3、线程池terminate()时,设置线程下次任务取到为终止符。

流程概要设计:

Python自定义线程池实现方法分析

详细代码:

import threading
import contextlib
from Queue import Queue
import time
class ThreadPool(object):
  def __init__(self, max_num):
    self.StopEvent = 0#线程任务终止符,当线程从队列获取到StopEvent时,代表此线程可以销毁。可设置为任意与任务有区别的值。
    self.q = Queue()
    self.max_num = max_num #最大线程数
    self.terminal = False  #是否设置线程池强制终止
    self.created_list = [] #已创建线程的线程列表
    self.free_list = [] #空闲线程的线程列表
    self.Deamon=False #线程是否是后台线程
  def run(self, func, args, callback=None):
    """
    线程池执行一个任务
    :param func: 任务函数
    :param args: 任务函数所需参数
    :param callback:
    :return: 如果线程池已经终止,则返回True否则None
    """
    if len(self.free_list) == 0 and len(self.created_list) < self.max_num:
      self.create_thread()
    task = (func, args, callback,)
    self.q.put(task)
  def create_thread(self):
    """
    创建一个线程
    """
    t = threading.Thread(target=self.call)
    t.setDaemon(self.Deamon)
    t.start()
    self.created_list.append(t)#将当前线程加入已创建线程列表created_list
  def call(self):
    """
    循环去获取任务函数并执行任务函数
    """
    current_thread = threading.current_thread()  #获取当前线程对象·
    event = self.q.get()  #从任务队列获取任务
    while event != self.StopEvent:  #判断获取到的任务是否是终止符
      func, arguments, callback = event#从任务中获取函数名、参数、和回调函数名
      try:
        result = func(*arguments)
        func_excute_status =True#func执行成功状态
      except Exception as e:
        func_excute_status = False
        result =None
        print '函数执行产生错误', e#打印错误信息
      if func_excute_status:#func执行成功后才能执行回调函数
        if callback is not None:#判断回调函数是否是空的
          try:
            callback(result)
          except Exception as e:
            print '回调函数执行产生错误', e # 打印错误信息
      with self.worker_state(self.free_list,current_thread):
        #执行完一次任务后,将线程加入空闲列表。然后继续去取任务,如果取到任务就将线程从空闲列表移除
        if self.terminal:#判断线程池终止命令,如果需要终止,则使下次取到的任务为StopEvent。
          event = self.StopEvent
        else: #否则继续获取任务
          event = self.q.get() # 当线程等待任务时,q.get()方法阻塞住线程,使其持续等待
    else:#若线程取到的任务是终止符,就销毁线程
      #将当前线程从已创建线程列表created_list移除
      self.created_list.remove(current_thread)
  def close(self):
    """
    执行完所有的任务后,所有线程停止
    """
    full_size = len(self.created_list)#按已创建的线程数量往线程队列加入终止符。
    while full_size:
      self.q.put(self.StopEvent)
      full_size -= 1
  def terminate(self):
    """
    无论是否还有任务,终止线程
    """
    self.terminal = True
    while self.created_list:
      self.q.put(self.StopEvent)
    self.q.queue.clear()#清空任务队列
  def join(self):
    """
    阻塞线程池上下文,使所有线程执行完后才能继续
    """
    for t in self.created_list:
      t.join()
  @contextlib.contextmanager#上下文处理器,使其可以使用with语句修饰
  def worker_state(self, state_list, worker_thread):
    """
    用于记录线程中正在等待的线程数
    """
    state_list.append(worker_thread)
    try:
      yield
    finally:
      state_list.remove(worker_thread)
if __name__ == '__main__':
  def Foo(arg):
    return arg
    # time.sleep(0.1)
  def Bar(res):
    print res
  pool=ThreadPool(5)
  # pool.Deamon=True#需在pool.run之前设置
  for i in range(1000):
    pool.run(func=Foo,args=(i,),callback=Bar)
  pool.close()
  pool.join()
  # pool.terminate()
  print "任务队列里任务数%s" %pool.q.qsize()
  print "当前存活子线程数量:%d" % threading.activeCount()
  print "当前线程创建列表:%s" %pool.created_list
  print "当前线程创建列表:%s" %pool.free_list

关于上下文处理:

来个简单例子说明:

下面的代码手动自定义了一个myopen方法,模拟我们常见的with open() as f:语句。具体的contextlib模块使用,会单独开章来将。

# coding:utf-8
import contextlib
@contextlib.contextmanager#定义该函数支持上下文with语句
def myopen(filename,mode):
  f=open(filename,mode)
  try:
    yield f.readlines()#正常执行返回f.readlines()
  except Exception as e:
    print e
  finally:
    f.close()#最后在with代码快执行完毕后返回执行finally下的f.close()实现关闭文件
if __name__ == '__main__':
  with myopen(r'c:\ip1.txt','r') as f:
    for line in f:
      print line

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python爬虫框架Scrapy安装使用步骤
Apr 01 Python
python实现跨文件全局变量的方法
Jul 07 Python
利用信号如何监控Django模型对象字段值的变化详解
Nov 27 Python
python实现自动发送报警监控邮件
Jun 21 Python
python 使用re.search()筛选后 选取部分结果的方法
Nov 28 Python
Python3安装psycopy2以及遇到问题解决方法
Jul 03 Python
基于Python函数和变量名解析
Jul 19 Python
由面试题加深对Django的认识理解
Jul 19 Python
Django 实现外键去除自动添加的后缀‘_id’
Nov 15 Python
将python包发布到PyPI和制作whl文件方式
Dec 25 Python
Python数据可视化实现漏斗图过程图解
Jul 20 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
May 25 Python
使用apidoc管理RESTful风格Flask项目接口文档方法
Feb 07 #Python
Python列表推导式、字典推导式与集合推导式用法实例分析
Feb 07 #Python
浅析Python3爬虫登录模拟
Feb 07 #Python
Python实现的三层BP神经网络算法示例
Feb 07 #Python
Python 12306抢火车票脚本
Feb 07 #Python
django限制匿名用户访问及重定向的方法实例
Feb 07 #Python
Python用 KNN 进行验证码识别的实现方法
Feb 06 #Python
You might like
我的论坛源代码(八)
2006/10/09 PHP
UTF8编码内的繁简转换的PHP类
2009/07/09 PHP
php缩小png图片不损失透明色的解决方法
2013/12/25 PHP
php截取指定2个字符之间字符串的方法
2015/04/15 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
谈谈从phpinfo中能获取哪些值得注意的信息
2017/03/28 PHP
javascript模版引擎-tmpl的bug修复与性能优化分析
2011/10/23 Javascript
调试Javascript代码(浏览器F12及VS中debugger关键字)
2013/01/25 Javascript
详解参数传递四种形式
2015/07/21 Javascript
js实现table添加行tr、删除行tr、清空行tr的简单实例
2016/10/15 Javascript
Bootstrap文件上传组件之bootstrap fileinput
2016/11/25 Javascript
js放大镜放大购物图片效果
2017/01/18 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
addEventListener()与removeEventListener()解析
2017/04/20 Javascript
利用Vue v-model实现一个自定义的表单组件
2017/04/27 Javascript
微信小程序学习笔记之文件上传、下载操作图文详解
2019/03/29 Javascript
微信小程序实现搜索功能并跳转搜索结果页面
2019/05/18 Javascript
Vue 路由间跳转和新开窗口的方式(query、params)
2019/12/25 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
2020/02/15 Javascript
浅谈Python由__dict__和dir()引发的一些思考
2017/10/30 Python
python编写简易聊天室实现局域网内聊天功能
2018/07/28 Python
pandas筛选某列出现编码错误的解决方法
2018/11/07 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
2018/12/15 Python
一步步教你用python的scrapy编写一个爬虫
2019/04/17 Python
利用Python脚本实现自动刷网课
2020/02/03 Python
pandas DataFrame 数据选取,修改,切片的实现
2020/04/24 Python
判断Threading.start新线程是否执行完毕的实例
2020/05/02 Python
Python+PyQt5+MySQL实现天气管理系统
2020/06/16 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
Python中的面向接口编程示例详解
2021/01/17 Python
皇家阿尔伯特瓷器美国官网:Royal Albert美国
2020/02/16 全球购物
简短的公司员工自我评价分享
2013/11/13 职场文书
大门门卫岗位职责
2013/11/30 职场文书
办理信用卡工作证明
2014/01/11 职场文书
二手书店创业计划书
2014/01/16 职场文书
初中家长评语大全
2014/12/26 职场文书