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 03 Python
python中self原理实例分析
Apr 30 Python
python处理按钮消息的实例详解
Jul 11 Python
python机器学习之决策树分类详解
Dec 20 Python
python快速建立超简单的web服务器的实现方法
Feb 17 Python
python读取和保存图片5种方法对比
Sep 12 Python
使用python opencv对目录下图片进行去重的方法
Jan 12 Python
python在openstreetmap地图上绘制路线图的实现
Jul 11 Python
python实现把两个二维array叠加成三维array示例
Nov 29 Python
pytorch 实现张量tensor,图片,CPU,GPU,数组等的转换
Jan 13 Python
PyTorch-GPU加速实例
Jun 23 Python
Python实现猜拳与猜数字游戏的方法详解
Apr 06 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中显示格式化的用户输入
2006/10/09 PHP
BBS(php & mysql)完整版(三)
2006/10/09 PHP
教你如何把一篇文章按要求分段
2006/10/09 PHP
windows xp下安装pear
2006/12/02 PHP
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
laravel中的错误与日志用法详解
2016/07/26 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
2020/05/02 PHP
jQuery1.5.1 animate方法源码阅读
2011/04/05 Javascript
JavaScript四种调用模式和this示例介绍
2014/01/02 Javascript
jQuery滚动加载图片实现原理
2015/12/14 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
AngularJS控制器controller给模型数据赋初始值的方法
2017/01/04 Javascript
原生JS实现几个常用DOM操作API实例
2017/01/19 Javascript
Angular2学习教程之TemplateRef和ViewContainerRef详解
2017/05/25 Javascript
vue2中使用less简易教程
2018/03/27 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
JavaScript实现选项卡效果的分析及步骤
2019/04/16 Javascript
在Layui中实现开关按钮的效果实例
2019/09/29 Javascript
进一步探究Python的装饰器的运用
2015/05/05 Python
python实现一个简单的ping工具方法
2019/01/31 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
2019/11/30 Python
pandas创建DataFrame的7种方法小结
2020/06/14 Python
浅谈Python3中print函数的换行
2020/08/05 Python
python3.9实现pyinstaller打包python文件成exe
2020/12/13 Python
使用CSS3编写灰阶滤镜来制作黑白照片效果的方法
2016/05/09 HTML / CSS
如何配置、使用和清除Smarty缓存
2015/12/23 面试题
C和C++经典笔试题附答案解析
2014/08/18 面试题
法学毕业生自荐信
2013/11/13 职场文书
秘书岗位职责
2013/11/18 职场文书
九年级科学教学反思
2014/01/29 职场文书
优秀医生事迹材料
2014/02/12 职场文书
党的群众路线教育实践活动个人整改落实情况汇报
2014/10/28 职场文书
幼儿园见习总结
2015/06/23 职场文书
培训简讯范文
2015/07/20 职场文书
大学生心理健康教育心得体会
2016/01/12 职场文书
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python