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随机生成数模块random使用实例
Apr 13 Python
django实现用户登陆功能详解
Dec 11 Python
python selenium UI自动化解决验证码的4种方法
Jan 05 Python
5款非常棒的Python工具
Jan 05 Python
手写一个python迭代器过程详解
Aug 27 Python
opencv实现简单人脸识别
Feb 19 Python
python中必要的名词解释
Nov 20 Python
对python中 math模块下 atan 和 atan2的区别详解
Jan 17 Python
基于Python的身份证验证识别和数据处理详解
Nov 14 Python
Python 批量下载阴阳师网站壁纸
May 19 Python
详解Go语言运用广度优先搜索走迷宫
Jun 23 Python
如何利用python实现Simhash算法
Jun 28 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
全国FM电台频率大全 - 17 湖北省
2020/03/11 无线电
PHP之autoload运行机制实例分析
2014/08/28 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
PHP实现负载均衡session共享redis缓存操作示例
2018/08/22 PHP
实例讲解通过​PHP创建数据库
2019/01/20 PHP
JavaScript 选中文字并响应获取的实现代码
2011/08/28 Javascript
圣诞节Merry Christmas给博客添加浪漫的下雪效果基于jquery实现
2012/12/27 Javascript
nodejs中exports与module.exports的区别详细介绍
2013/01/14 NodeJs
Js 代码中,ajax请求地址后加随机数防止浏览器缓存的原因
2013/05/07 Javascript
js实现字符串的16进制编码不加密
2014/04/25 Javascript
jquery实现图片按比例缩放示例
2014/07/01 Javascript
Angular.js如何从PHP读取后台数据
2016/03/24 Javascript
javascript日期比较方法实例分析
2016/06/17 Javascript
JS实现动画兼容性的transition和transform实例分析
2016/12/13 Javascript
JS实现简易的图片拖拽排序实例代码
2017/06/09 Javascript
Three.js中网格对象MESH的属性与方法详解
2017/09/27 Javascript
基于nodejs res.end和res.send的区别
2018/05/14 NodeJs
利用JS实现一个同Excel表现的智能填充算法
2018/08/13 Javascript
nodejs一个简单的文件服务器的创建方法
2019/09/13 NodeJs
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
[48:35]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 TNC vs Optic
2018/04/03 DOTA
python基础教程之popen函数操作其它程序的输入和输出示例
2014/02/10 Python
ubuntu 18.04搭建python环境(pycharm+anaconda)
2019/06/14 Python
pytorch索引查找 index_select的例子
2019/08/18 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
用python爬取历史天气数据的方法示例
2019/12/30 Python
python 判断txt每行内容中是否包含子串并重新写入保存的实例
2020/03/12 Python
opencv 图像滤波(均值,方框,高斯,中值)
2020/07/08 Python
利用CSS3的线性渐变linear-gradient制作边框的示例
2016/06/02 HTML / CSS
La Senza官网:北美顶尖性感内衣品牌
2018/08/03 全球购物
Columbia Sportswear法国官网:全球户外品牌
2020/09/25 全球购物
北京振戎融通Java面试题
2015/09/03 面试题
群众路线教育实践活动实施方案
2014/10/31 职场文书
2016年优秀共产党员先进事迹材料
2016/02/29 职场文书
2019送给家人们的中秋节祝福语
2019/08/15 职场文书
pycharm2021激活码使用教程(永久激活亲测可用)
2021/03/30 Python