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通过select实现异步IO的方法
Jun 04 Python
Python脚本暴力破解栅栏密码
Oct 19 Python
解决pycharm无法调用pip安装的包问题
May 18 Python
Python字符串的常见操作实例小结
Apr 08 Python
对python3 Serial 串口助手的接收读取数据方法详解
Jun 12 Python
python读取并写入mat文件的方法
Jul 12 Python
Python+Tensorflow+CNN实现车牌识别的示例代码
Oct 11 Python
如何更改 pandas dataframe 中两列的位置
Dec 27 Python
python opencv进行图像拼接
Mar 27 Python
python和php哪个容易学
Jun 19 Python
浅析Python 序列化与反序列化
Aug 05 Python
Python 实现定积分与二重定积分的操作
May 26 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数据类型的总结分析
2013/06/13 PHP
zf框架的session会话周期及次数限制使用示例
2014/03/13 PHP
PHP输出九九乘法表代码实例
2015/03/27 PHP
ZF框架实现发送邮件的方法
2015/12/03 PHP
ThinkPHP5&5.1框架关联模型分页操作示例
2019/08/03 PHP
基于Laravel 5.2 regex验证的正确写法
2019/09/29 PHP
javascript中基本类型和引用类型的区别分析
2015/05/12 Javascript
jquery转盘抽奖功能实现
2015/11/13 Javascript
jQuery Validate初步体验(一)
2015/12/12 Javascript
chrome浏览器如何断点调试异步加载的JS
2016/09/05 Javascript
微信小程序 实战程序简易新闻的制作
2017/01/09 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
nodejs中sleep功能实现暂停几秒的方法
2017/07/12 NodeJs
jQuery常用选择器详解
2017/07/17 jQuery
JS实现的简单表单验证功能完整实例
2017/10/14 Javascript
Vue实现web分页组件详解
2017/11/28 Javascript
switchery按钮的使用方法
2017/12/18 Javascript
vue代码分割的实现(codesplit)
2018/11/13 Javascript
Node.js assert断言原理与用法分析
2019/01/04 Javascript
原生JS实现逼真的图片3D旋转效果详解
2019/02/16 Javascript
学习RxJS之JavaScript框架Cycle.js
2019/06/17 Javascript
微信小程序开发注意指南和优化实践(小结)
2019/06/21 Javascript
小程序的上传文件接口的注意要点解析
2019/09/17 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
Python正则表达式指南 推荐
2018/10/09 Python
Python创建字典的八种方式
2019/02/27 Python
python生成器用法实例详解
2019/11/22 Python
Python3 A*寻路算法实现方式
2019/12/24 Python
css3 flex布局 justify-content:space-between 最后一行左对齐
2020/01/02 HTML / CSS
Yves Rocher捷克官方网站:植物化妆品的创造者
2019/07/31 全球购物
保荐人的岗位职责
2013/11/19 职场文书
简历中自我评价范文3则
2013/12/14 职场文书
办公室文员工作职责
2014/01/31 职场文书
党支部四风整改方案
2014/10/25 职场文书
营销计划书
2015/01/17 职场文书
2015年化验室工作总结
2015/04/23 职场文书