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深入学习之对象的属性
Aug 31 Python
pandas中apply和transform方法的性能比较及区别介绍
Oct 30 Python
Python split() 函数拆分字符串将字符串转化为列的方法
Jul 16 Python
python 遍历pd.Series的index和value
Nov 26 Python
PyTorch中topk函数的用法详解
Jan 02 Python
Python+OpenCV实现将图像转换为二进制格式
Jan 09 Python
Python脚本导出为exe程序的方法
Mar 25 Python
python数据类型强制转换实例详解
Jun 22 Python
python爬虫分布式获取数据的实例方法
Nov 26 Python
python 装饰器的基本使用
Jan 13 Python
使用numpngw和matplotlib生成png动画的示例代码
Jan 24 Python
Python趣味挑战之教你用pygame画进度条
May 31 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和ACCESS写聊天室(四)
2006/10/09 PHP
phpmyadmin MySQL 加密配置方法
2009/07/05 PHP
PHP初学者常见问题集合 修正版(21问答)
2010/03/23 PHP
Zend Framework框架教程之Zend_Db_Table_Rowset用法实例分析
2016/03/21 PHP
php中照片旋转 (orientation) 问题的正确处理
2017/02/16 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
在jQuery中 常用的选择器介绍
2013/04/16 Javascript
javascript禁用Tab键脚本实例
2013/11/22 Javascript
JavaSript中变量的作用域闭包的深入理解
2014/05/12 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
基于jquery的手风琴图片展示效果实现方法
2014/12/16 Javascript
js window对象属性和方法相关资料整理
2015/11/11 Javascript
Active控件问题小结(附解决办法)
2016/06/09 Javascript
jQuery操作json常用方法示例
2017/01/04 Javascript
VUE饿了么树形控件添加增删改功能的示例代码
2017/10/17 Javascript
浅谈在vue项目中如何定义全局变量和全局函数
2017/10/24 Javascript
vue2.x+webpack快速搭建前端项目框架详解
2017/11/30 Javascript
javaScript日期工具类DateUtils详解
2017/12/08 Javascript
详解VUE Element-UI多级菜单动态渲染的组件
2019/04/25 Javascript
layui上传图片到服务器的非项目目录下的方法
2019/09/26 Javascript
JS实现拼图游戏
2021/01/29 Javascript
[03:58]2014DOTA2国际邀请赛 龙宝赛后解密DK获胜之道
2014/07/14 DOTA
Python中的yield浅析
2014/06/16 Python
Python中的ConfigParser模块使用详解
2015/05/04 Python
django之session与分页(实例讲解)
2017/11/13 Python
python 实现视频 图像帧提取
2019/12/10 Python
Python Django2 model 查询介绍(条件、范围、模糊查询)
2020/03/16 Python
python zip,lambda,map函数代码实例
2020/04/04 Python
python爬取音频下载的示例代码
2020/10/19 Python
python 窃取摄像头照片的实现示例
2021/01/08 Python
美国购买和销售礼品卡平台:Raise
2017/01/13 全球购物
美国瑜伽品牌:Gaiam
2017/10/31 全球购物
Java编程面试题
2016/04/04 面试题
文员试用期转正自我鉴定
2014/09/14 职场文书
使用SQL实现车流量的计算的示例代码
2022/02/28 SQL Server
Javascript webpack动态import
2022/04/19 Javascript