python多线程抽象编程模型详解


Posted in Python onMarch 20, 2019

最近需要完成一个多线程下载的工具,对其中的多线程下载进行了一个抽象,可以对所有需要使用到多线程编程的地方统一使用这个模型来进行编写。

主要结构:

1、基于Queue标准库实现了一个类似线程池的工具,用户指定提交任务线程submitter与工作线程worker数目,所有线程分别设置为后台运行,提供等待线程运行完成的接口。

2、所有需要完成的任务抽象成task,提供单独的无参数调用方式,供worker线程调用;task以生成器的方式作为参数提供,供submitter调用。

3、所有需要进行线程交互的信息放在context类中。

主要实现代码如下:

#Submitter线程类实现,主要是`task_generator`调用
class SubmitterThread(threading.Thread):
  _DEFAULT_WAIT_TIMEOUT = 2 #seconds
  def __init__(self, queue, task_gen, timeout=2):
    super(SubmitterThread, self).__init__()
    self.queue = queue
    if not isinstance(timeout, int):
      _logger.error('Thread wait timeout value error: %s, '
             'use default instead.' % timeout)
      self.timeout = self._DEFAULT_WAIT_TIMEOUT
    self.timeout = timeout
    self.task_generator = task_gen

  def run(self):
    while True:
      try:
        task = self.task_generator.next()
        self.queue.put(task, True, self.timeout)
      except Queue.Full:
        _logger.debug('Task queue is full. %s wait %d second%s timeout' %
               (self.name, self.timeout, 's' if (self.timeout > 1) else ''))
        break
      except (StopIteration, ValueError) as e:
        _logger.debug('Task finished')
        break
#Worker线程实现,主要就是try块内的func调用
class WorkerThread(threading.Thread):
  _DEFAULT_WAIT_TIMEOUT = 2 #seconds
  def __init__(self, queue, timeout=2):
    super(WorkerThread, self).__init__()
    self.queue = queue
    if not isinstance(timeout, int):
      _logger.error('Thread wait timeout value error: %s, '
             'use default instead.' % timeout)
      self.timeout = self._DEFAULT_WAIT_TIMEOUT
    self.timeout = timeout

  def run(self):
    while True:
      try:
        func = self.queue.get(True, self.timeout)
      except Queue.Empty:
        _logger.debug('Task queue is empty. %s wait %d second%s timeout' %
               (self.name, self.timeout, 's' if (self.timeout > 1) else ''))
        break

      if not callable(func):
        time.sleep(1)
      try:
        func()
      except Exception as e:
        _logger.error('Thread %s running occurs error: %s' %
               (self.name, e))
        print('Thread running error: %s' % e)
class Executor(object):
  """
  The really place to execute executor
  """
  thread_list = []
  submitters = 0
  workers = 0
  queue = None
  task_generator = None
  timeout = 0
  def __init__(self, task_gen, submitters=1, workers=1 , timeout=2):
    if len(self.thread_list) != 0:
      raise RuntimeError('Executor can only instance once.')
    self.queue = Queue.Queue(maxsize=submitters * 2 + workers * 2)
    self.submitters = submitters
    self.workers = workers
    self.task_generator = task_gen
    self.timeout = timeout

  def start(self):
    for i in range(self.submitters):
      submitter = SubmitterThread(self.queue, self.task_generator, self.timeout)
      self.thread_list.append(submitter)
      submitter.setName('Submitter-%d' % i)
      submitter.setDaemon(True)
      submitter.start()
    for i in range(self.workers):
      worker = WorkerThread(self.queue, self.timeout)
      self.thread_list.append(worker)
      worker.setName('Worker-%d' % i)
      worker.setDaemon(True)
      worker.start()

  def is_alive(self):
    alive = False
    for t in self.thread_list:
      if t.isAlive():
        alive = True
        break
    return alive

  def wait_to_shutdown(self):
    _logger.debug('Start to wait to shutdown')
    for t in self.thread_list:
      t.join()
      _logger.debug('Shutdown thread : %s' % t.name)

Executor类保存了线程池,提供相应接口。有了这个抽象之后,只需要实例化Executor类的对象,然后调用start方法进行多线程任务的运行。并可以用is_alive等接口再主线程内进行其他处理。

后续再使用这个抽象进行实际多线程任务的实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用python绘制人人网好友关系图示例
Apr 01 Python
python使用marshal模块序列化实例
Sep 25 Python
详解在Python的Django框架中创建模板库的方法
Jul 20 Python
Python使用poplib模块和smtplib模块收发电子邮件的教程
Jul 02 Python
Python中django学习心得
Dec 06 Python
Python数据类型之列表和元组的方法实例详解
Jul 08 Python
基于sklearn实现Bagging算法(python)
Jul 11 Python
解决python中导入win32com.client出错的问题
Jul 26 Python
使用Pandas将inf, nan转化成特定的值
Dec 19 Python
windows、linux下打包Python3程序详细方法
Mar 17 Python
jupyter 使用Pillow包显示图像时inline显示方式
Apr 24 Python
Pytorch如何切换 cpu和gpu的使用详解
Mar 01 Python
基于python生成器封装的协程类
Mar 20 #Python
python实现栅栏加解密 支持密钥加密
Mar 20 #Python
python实现Virginia无密钥解密
Mar 20 #Python
python实现维吉尼亚加密法
Mar 20 #Python
Python multiprocess pool模块报错pickling error问题解决方法分析
Mar 20 #Python
python实现对输入的密文加密
Mar 20 #Python
python实现字符串加密成纯数字
Mar 19 #Python
You might like
PHP下判断网址是否有效的代码
2011/10/08 PHP
PHP获取当前系统时间的方法小结
2018/10/03 PHP
优化JavaScript脚本的性能的几个注意事项
2006/12/22 Javascript
javascript实现 在光标处插入指定内容
2007/05/25 Javascript
十个优秀的Ajax/Javascript实例网站收集
2010/03/31 Javascript
JavaScript 轻松搞定快捷留言功能 只需一行代码
2010/04/01 Javascript
JS实现self的resend
2010/07/22 Javascript
XMLHTTP 乱码的解决方法(UTF8,GB2312 编码 解码)
2011/01/12 Javascript
Javascript 八进制转义字符(8进制)
2011/04/08 Javascript
js实现运动logo图片效果及运动元素对象sportBox使用方法
2012/12/25 Javascript
JavaScript中匿名、命名函数的性能测试
2014/09/04 Javascript
node.js中的url.resolve方法使用说明
2014/12/10 Javascript
JavaScript获取伪元素(Pseudo-Element)属性的方法技巧
2015/03/13 Javascript
浅谈javascript的分号的使用
2015/05/12 Javascript
Easyui和zTree两种方式分别实现树形下拉框
2017/08/04 Javascript
使用json-server简单完成CRUD模拟后台数据的方法
2018/07/12 Javascript
ES10 特性的完整指南小结
2019/03/04 Javascript
npm的lock机制解析
2019/06/20 Javascript
ES6函数和数组用法实例分析
2020/05/23 Javascript
vue实现div可拖动位置也可改变盒子大小的原理
2020/09/16 Javascript
基于vue+echarts数据可视化大屏展示的实现
2020/12/25 Vue.js
python的迭代器与生成器实例详解
2014/07/16 Python
使用requests库制作Python爬虫
2018/03/25 Python
python批量识别图片指定区域文字内容
2019/04/30 Python
Django+RestFramework API接口及接口文档并返回json数据操作
2020/07/12 Python
sublime3之内网安装python插件Anaconda的流程
2020/11/10 Python
美国彩妆品牌:Coastal Scents
2017/04/01 全球购物
新学期班主任寄语
2014/01/18 职场文书
军神教学反思
2014/02/04 职场文书
产品包装策划方案
2014/05/18 职场文书
教师自我剖析材料(四风问题)
2014/09/30 职场文书
离婚协议书范文2014(夫妻感情破裂)
2014/12/14 职场文书
2015双创工作总结
2015/07/24 职场文书
PyTorch的Debug指南
2021/05/07 Python
JavaScript原始值与包装对象的详细介绍
2021/05/11 Javascript
python热力图实现的完整实例
2022/06/25 Python