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 23 Python
numpy中以文本的方式存储以及读取数据方法
Jun 04 Python
idea创建springMVC框架和配置小文件的教程图解
Sep 18 Python
Python设计模式之迭代器模式原理与用法实例分析
Jan 10 Python
解决django服务器重启端口被占用的问题
Jul 26 Python
基于python实现的百度新歌榜、热歌榜下载器(附代码)
Aug 05 Python
Django使用uwsgi部署时的配置以及django日志文件的处理方法
Aug 30 Python
pandas中遍历dataframe的每一个元素的实现
Oct 23 Python
Python如何在DataFrame增加数值
Feb 14 Python
Python任务调度利器之APScheduler详解
Apr 02 Python
opencv 阈值分割的具体使用
Jul 08 Python
详解在Python中使用Torchmoji将文本转换为表情符号
Jul 27 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连mysql和oracle数据库性能比较
2006/10/09 PHP
PHP+javascript液晶时钟
2006/10/09 PHP
使用PHP获取网络文件的实现代码
2010/01/01 PHP
Php连接及读取和写入mysql数据库的常用代码
2014/08/11 PHP
讲解WordPress开发中一些常用的debug技巧
2015/12/18 PHP
wordpress网站转移到本地运行测试的方法
2017/03/15 PHP
jquery 缓存问题的几个解决方法
2013/11/11 Javascript
使用VS开发 Node.js指南
2015/01/06 Javascript
Jquery树插件zTree用法入门教程
2015/02/17 Javascript
JavaScript实现表格点击排序的方法
2015/05/11 Javascript
利用JavaScript的AngularJS库制作电子名片的方法
2015/06/18 Javascript
基于JS实现导航条之调用网页助手小精灵的方法
2016/06/17 Javascript
JavaScript组合模式学习要点
2016/08/26 Javascript
微信小程序 location API接口详解及实例代码
2016/10/12 Javascript
微信小程序之数据双向绑定与数据操作
2017/05/12 Javascript
详解Webpack+Babel+React开发环境的搭建的方法步骤
2018/01/09 Javascript
JS改变页面颜色源码分享
2018/02/24 Javascript
Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能
2018/08/12 Javascript
详解Vue内部怎样处理props选项的多种写法
2018/11/06 Javascript
[02:38]2018年度DOTA2最佳劣单位选手-完美盛典
2018/12/17 DOTA
Python3转换html到pdf的不同解决方案
2019/03/11 Python
python多线程与多进程及其区别详解
2019/08/08 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
python 下载文件的多种方法汇总
2020/11/17 Python
python基于opencv实现人脸识别
2021/01/04 Python
CSS3制作皮卡丘动画壁纸的示例
2020/11/02 HTML / CSS
加拿大城市本地限时优惠:Buytopia.ca
2018/09/19 全球购物
信息工程学院毕业生推荐信
2013/11/05 职场文书
2013年员工自我评价范文
2013/12/27 职场文书
骨干教师培训感言
2014/01/16 职场文书
网管求职信
2014/03/03 职场文书
马云北大演讲完整版:真心话,什么才是阿里的核心竞争力?
2014/04/04 职场文书
乡镇务虚会发言材料
2014/10/20 职场文书
大学生个人学年总结
2015/02/15 职场文书
《遗弃》开发商删推文要跑路?官方回应:还在开发
2022/04/03 其他游戏