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入门篇之数字
Oct 20 Python
python实现超简单端口转发的方法
Mar 13 Python
python实现从ftp服务器下载文件的方法
Apr 30 Python
python处理图片之PIL模块简单使用方法
May 11 Python
python 获取list特定元素下标的实例讲解
Apr 09 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
Jun 09 Python
pyqt5 QProgressBar清空进度条的实例
Jun 21 Python
python实现udp传输图片功能
Mar 20 Python
Django:使用filter的pk进行多值查询操作
Jul 15 Python
Python random模块的使用示例
Oct 10 Python
使用Python封装excel操作指南
Jan 29 Python
pytorch 预训练模型读取修改相关参数的填坑问题
Jun 05 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下把数组保存为文件格式的实例应用
2010/02/08 PHP
php中convert_uuencode()与convert_uuencode函数用法实例
2014/11/22 PHP
php导入大量数据到mysql性能优化技巧
2014/12/29 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
setTimeout与setInterval在不同浏览器下的差异
2010/01/24 Javascript
理解Javascript_03_javascript全局观
2010/10/11 Javascript
使用jquery mobile做幻灯播放效果实现步骤
2013/01/04 Javascript
jQuery 绑定事件到动态创建的元素上的方法实例
2013/08/18 Javascript
jQuery的图片滑块焦点图插件整理推荐
2014/12/07 Javascript
JavaScript类继承及实例化的方法
2015/07/25 Javascript
javascript实现二级级联菜单的简单制作
2015/11/19 Javascript
在Node.js中使用Javascript Generators详解
2016/05/05 Javascript
angular.js 路由及页面传参示例
2017/02/24 Javascript
Angular.js中ng-include用法及多标签页面的实现方式详解
2017/05/07 Javascript
Angular中$broadcast和$emit的使用方法详解
2017/05/22 Javascript
解决iView中时间控件选择的时间总是少一天的问题
2018/03/15 Javascript
JavaScript遍历数组的三种方法map、forEach与filter实例详解
2019/02/27 Javascript
微信小程序 wepy框架与iview-weapp的用法详解
2019/04/10 Javascript
JavaScript遍历数组的方法代码实例
2020/01/14 Javascript
微信小程序实现滑动操作代码
2020/04/23 Javascript
jQuery实现评论模块
2020/08/19 jQuery
python实现用户登陆邮件通知的方法
2015/07/09 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
2018/01/04 Python
Python unittest 简单实现参数化的方法
2018/11/30 Python
python使用ctypes库调用DLL动态链接库
2020/10/22 Python
CSS3之多背景background使用示例
2013/10/18 HTML / CSS
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
2013/01/09 HTML / CSS
h5页面背景图很长要有滚动条滑动效果的实现
2021/01/27 HTML / CSS
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
婚前财产公证书
2014/04/10 职场文书
机电专业毕业生求职信
2014/07/01 职场文书
大学生实习推荐信
2015/03/27 职场文书
乒乓球比赛通知
2015/04/27 职场文书
演讲比赛主持词
2015/06/29 职场文书
golang 语言中错误处理机制
2021/08/30 Golang
Apache自带的ab压力测试工具的实现
2022/07/23 Servers