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文件和目录操作详解
Feb 08 Python
使用Python实现下载网易云音乐的高清MV
Mar 16 Python
利用一个简单的例子窥探CPython内核的运行机制
Mar 30 Python
Python基于回溯法解决01背包问题实例
Dec 06 Python
Python爬虫_城市公交、地铁站点和线路数据采集实例
Jan 10 Python
python基于http下载视频或音频
Jun 20 Python
使用python3实现操作串口详解
Jan 01 Python
python生成带有表格的图片实例
Feb 03 Python
Python大数据之从网页上爬取数据的方法详解
Nov 16 Python
django-crontab实现服务端的定时任务的示例代码
Feb 17 Python
Matplotlib使用字符串代替变量绘制散点图的方法
Feb 17 Python
Python+Tkinter打造签名设计工具
Apr 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/23 PHP
PHP 验证码不显示只有一个小红叉的解决方法
2013/09/30 PHP
php校验表单检测字段是否为空的方法
2015/03/20 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
2016/03/22 PHP
ExtJs的Date格式字符代码
2010/12/30 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
2014/08/16 Javascript
浅谈JavaScript中运算符的优先级
2015/07/07 Javascript
轻松学习jQuery插件EasyUI EasyUI实现树形网络基本操作(2)
2015/11/30 Javascript
15款最好的Bootstrap在线编辑器
2016/08/03 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
JavaScript实现简单的四则运算计算器完整实例
2017/04/28 Javascript
layui弹出层效果实现代码
2017/05/19 Javascript
关于vue.js组件数据流的问题
2017/07/26 Javascript
详解Vue组件实现tips的总结
2017/11/01 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
浅谈微信小程序列表埋点曝光指南
2019/10/15 Javascript
Vue最新防抖方案(必看篇)
2019/10/30 Javascript
[04:39]显微镜下的DOTA2第十三期—Pis卡尔个人秀
2014/04/04 DOTA
[01:56]生活中的妖精之七夕特别档
2016/08/09 DOTA
[53:50]CHAOS vs Mineski 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
关于不懂Chromedriver如何配置环境变量问题解决方法
2019/06/12 Python
django框架模板中定义变量(set variable in django template)的方法分析
2019/06/24 Python
PyTorch: 梯度下降及反向传播的实例详解
2019/08/20 Python
调整Jupyter notebook的启动目录操作
2020/04/10 Python
一款利用html5和css3实现的3D立方体旋转效果教程
2016/04/26 HTML / CSS
华丽的手绘陶瓷:MacKenzie-Childs
2017/02/04 全球购物
Forever 21美国官网:美国标志性快时尚品牌
2017/02/20 全球购物
印度尼西亚最大的电商平台:Tokopedia(印尼版淘宝)
2017/12/02 全球购物
施华洛世奇美国官网:SWAROVSKI美国
2018/02/08 全球购物
澳大利亚排名第一的狂热牛仔品牌:ONETEASPOON
2018/11/20 全球购物
欧克利英国官网:Oakley英国
2019/08/24 全球购物
武汉高蓝德国际.net机试
2016/06/24 面试题
美术专业个人自我评价
2014/01/18 职场文书
办公室秘书自我鉴定
2014/01/18 职场文书
Apache Hudi 加速传统的批处理模式
2022/04/24 Servers
Windows Server 2016服务器用户管理及远程授权图文教程
2022/08/14 Servers