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的re模块正则表达式操作
May 25 Python
Python设计模式之命令模式简单示例
Jan 10 Python
Python 普通最小二乘法(OLS)进行多项式拟合的方法
Dec 29 Python
Python3匿名函数lambda介绍与使用示例
May 18 Python
用Python画一个LinkinPark的logo代码实例
Sep 10 Python
python 实现让字典的value 成为列表
Dec 16 Python
Python中sorted()排序与字母大小写的问题
Jan 14 Python
Python利用全连接神经网络求解MNIST问题详解
Jan 14 Python
如何用python处理excel表格
Jun 09 Python
如何卸载python插件
Jul 08 Python
10个python爬虫入门实例(小结)
Nov 01 Python
python 读取串口数据的示例
Nov 09 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脚本
2006/11/26 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
PHP实现的sqlite数据库连接类
2014/12/12 PHP
php中使用in_array() foreach array_search() 查找数组是否包含时的性能对比
2015/04/14 PHP
YII Framework框架教程之使用YIIC快速创建YII应用详解
2016/03/15 PHP
Laravel中unique和exists验证规则的优化详解
2018/01/28 PHP
jquery 插件 web2.0分格的分页脚本,可用于ajax无刷新分页
2008/12/25 Javascript
基于jquery的$.ajax async使用
2011/10/19 Javascript
jquery图片延迟加载 前端开发技能必备系列
2012/06/18 Javascript
JS 数字转换研究总结
2013/12/26 Javascript
javascript瀑布流式图片懒加载实例
2020/06/28 Javascript
基于百度地图实现产品销售的单位位置查看功能设计与实现
2016/10/21 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
JavaScript页面加载事件实例讲解
2019/09/01 Javascript
打印出python 当前全局变量和入口参数的所有属性
2009/07/01 Python
Python调用C语言的方法【基于ctypes模块】
2018/01/22 Python
利用arcgis的python读取要素的X,Y方法
2018/12/22 Python
Python中GeoJson和bokeh-1的使用讲解
2019/01/03 Python
Python交互式图形编程的实现
2019/07/25 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
Python小白不正确的使用类变量实例
2020/05/29 Python
Python闭包及装饰器运行原理解析
2020/06/17 Python
python语言实现贪吃蛇游戏
2020/11/13 Python
教学实习自我评价
2014/01/28 职场文书
应届毕业生应聘自荐信范文
2014/02/26 职场文书
中秋寄语大全
2014/04/11 职场文书
留学生求职信
2014/06/03 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
幼儿园教师师德承诺书
2015/04/28 职场文书
中学教师师德师风承诺书
2015/04/28 职场文书
开学随笔
2015/08/15 职场文书
2016年“我们的节日·重阳节”主题活动总结
2016/04/01 职场文书
如何写一份成功的商业计划书
2019/06/25 职场文书
导游词之丽江普济寺
2019/10/22 职场文书
Python爬虫之爬取某文库文档数据
2021/04/21 Python
Python3的进程和线程你了解吗
2022/03/16 Python