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内置函数dir详解
Apr 14 Python
Python实现基于权重的随机数2种方法
Apr 28 Python
以windows service方式运行Python程序的方法
Jun 03 Python
python K近邻算法的kd树实现
Sep 06 Python
Python数据可视化教程之Matplotlib实现各种图表实例
Jan 13 Python
python实现AES和RSA加解密的方法
Mar 28 Python
pygame实现非图片按钮效果
Oct 29 Python
Python argparse模块应用实例解析
Nov 15 Python
python argparse传入布尔参数false不生效的解决
Apr 20 Python
Python中实现输入一个整数的案例
May 03 Python
Django 如何使用日期时间选择器规范用户的时间输入示例代码详解
May 22 Python
详解Python调用系统命令的六种方法
Jan 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
基于MySQL到MongoDB简易对照表的详解
2013/06/03 PHP
php序列化函数serialize() 和 unserialize() 与原生函数对比
2015/05/08 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
PHP7扩展开发之hello word实现方法详解
2018/01/15 PHP
PHP反射原理与用法深入分析
2019/09/28 PHP
新手入门常用代码集锦
2007/01/11 Javascript
jQuery 连续列表实现代码
2009/12/21 Javascript
Jquery显示、隐藏元素以及添加删除样式
2013/08/09 Javascript
js截取字符串的两种方法及区别详解
2013/11/05 Javascript
利用js制作html table分页示例(js实现分页)
2014/04/25 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
2017/04/11 Javascript
electron demo项目npm install安装失败的解决方法
2018/02/06 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
2018/08/10 Javascript
vue quill editor 使用富文本添加上传音频功能
2020/01/14 Javascript
微信小程序吸底区域适配iPhoneX的实现
2020/04/09 Javascript
Vue实现简单的跑马灯
2020/05/25 Javascript
js实现搜索提示框效果
2020/09/05 Javascript
python使用nntp读取新闻组内容的方法
2015/05/08 Python
对python 各种删除文件失败的处理方式分享
2018/04/24 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
python无限生成不重复(字母,数字,字符)组合的方法
2018/12/04 Python
详解python数据结构和算法
2019/04/18 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
2019/06/18 Python
Python3爬虫中关于中文分词的详解
2020/07/29 Python
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
2012/12/13 HTML / CSS
HTML5 绘制图像(上)之:关于canvas元素引领下一代web页面的问题
2013/04/24 HTML / CSS
Spartoo瑞典:鞋子、包包和衣服
2018/09/15 全球购物
广州喜创信息技术有限公司JAVA软件工程师笔试题
2012/10/17 面试题
完美的中文自荐信
2014/05/24 职场文书
建筑工地大门标语
2014/06/18 职场文书
2014乡镇党政班子四风问题思想汇报
2014/09/14 职场文书
建筑工地文明标语
2014/10/09 职场文书
如何书写你的职业生涯规划书?
2019/06/27 职场文书
SQL 窗口函数实现高效分页查询的案例分析
2021/05/21 SQL Server
CSS实现单选折叠菜单功能
2021/11/01 HTML / CSS