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生成随机验证码(中文验证码)示例
Apr 03 Python
python实现的希尔排序算法实例
Jul 01 Python
python实现文件路径和url相互转换的方法
Jul 06 Python
python使用fcntl模块实现程序加锁功能示例
Jun 23 Python
用python做一个搜索引擎(Pylucene)的实例代码
Jul 05 Python
CentOS中升级Python版本的方法详解
Jul 10 Python
python中numpy.zeros(np.zeros)的使用方法
Nov 07 Python
浅谈利用numpy对矩阵进行归一化处理的方法
Jul 11 Python
python标记语句块使用方法总结
Aug 05 Python
Python如何输出整数
Jun 07 Python
Python 如何利用ffmpeg 处理视频素材
Nov 27 Python
如何基于python实现单目三维重建详解
Jun 25 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中提问频率最高的11个面试题和答案
2014/09/02 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
Thinkphp5框架简单实现钩子(Hook)行为的方法示例
2019/09/03 PHP
Js获取事件对象代码
2010/08/05 Javascript
JS模拟面向对象全解(一、类型及传递)
2011/07/13 Javascript
eval的两组性能测试数据
2012/08/17 Javascript
JSONP跨域的原理解析及其实现介绍
2014/03/22 Javascript
Node.js抓取中文网页乱码问题和解决方法
2015/02/10 Javascript
jQueryUI中的datepicker使用方法详解
2016/05/25 Javascript
jQGrid动态填充select下拉框的选项值(动态填充)
2016/11/28 Javascript
JS新包管理工具yarn和npm的对比与使用入门
2016/12/09 Javascript
Bootstrap fileinput文件上传预览插件使用详解
2017/05/16 Javascript
JS实现搜索关键词的智能提示功能
2017/07/07 Javascript
自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结
2017/08/18 Javascript
JS实现身份证输入框的输入效果
2017/08/21 Javascript
VueJS组件之间通过props交互及验证的方式
2017/09/04 Javascript
bootstrap 路径导航 分页 进度条的实例代码
2018/08/06 Javascript
Vue.Draggable拖拽功能的配置使用方法
2020/07/29 Javascript
js 下拉菜单点击旁边收起实现(踩坑记)
2019/09/29 Javascript
vue 父组件通过$refs获取子组件的值和方法详解
2019/11/07 Javascript
重置Redux的状态数据的方法实现
2019/11/18 Javascript
原生js实现点击轮播切换图片
2020/02/11 Javascript
JS实现购物车基本功能
2020/11/08 Javascript
numpy实现合并多维矩阵、list的扩展方法
2018/05/08 Python
python turtle库画一个方格和圆实例
2019/06/27 Python
如何解决tensorflow恢复模型的特定值时出错
2020/02/06 Python
突袭HTML5之Javascript API扩展1—Web Worker异步执行及相关概述
2013/01/31 HTML / CSS
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
玩具反斗城美国官网:Toys"R"Us
2016/09/17 全球购物
英国最大的独立摄影零售商:Park Cameras
2019/11/27 全球购物
如何用JQuery进行表单验证
2013/05/29 面试题
班委竞选演讲稿
2014/04/28 职场文书
党员四风剖析材料
2014/08/27 职场文书
2015年学校教务处工作总结
2015/05/11 职场文书
新娘婚礼致辞
2015/07/27 职场文书
详解Python小数据池和代码块缓存机制
2021/04/07 Python