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中使用M2Crypto模块实现AES加密的教程
Apr 08 Python
Python实现字符串反转的常用方法分析【4种方法】
Sep 30 Python
Python内存管理方式和垃圾回收算法解析
Nov 11 Python
python爬虫获取多页天涯帖子
Feb 23 Python
Python中的pack和unpack的使用
Mar 12 Python
python如何让类支持比较运算
Mar 20 Python
python pandas dataframe 按列或者按行合并的方法
Apr 12 Python
python plotly画柱状图代码实例
Dec 13 Python
Python接口测试get请求过程详解
Feb 28 Python
python3读取autocad图形文件.py实例
Jun 05 Python
使用keras框架cnn+ctc_loss识别不定长字符图片操作
Jun 29 Python
Python如何设置指定窗口为前台活动窗口
Aug 12 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下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
PHP中uploaded_files函数使用方法详解
2011/03/09 PHP
php中删除字符串中最先出现某个字符的实现代码
2013/02/03 PHP
19个超实用的PHP代码片段
2014/03/14 PHP
php 算法之实现相对路径的实例
2017/10/17 PHP
JS实现屏蔽shift,Ctrl,alt等功能键的方法
2015/06/01 Javascript
浅谈js中StringBuffer类的实现方法及使用
2016/09/02 Javascript
vue2 中如何实现动态表单增删改查实例
2017/06/09 Javascript
基于JSONP原理解析(推荐)
2017/12/04 Javascript
layui的table中显示图片方法
2018/08/17 Javascript
Vue.js实现备忘录功能
2019/06/26 Javascript
Angular8 实现table表格表头固定效果
2020/01/03 Javascript
ng-alain的sf如何自定义部件的流程
2020/06/12 Javascript
TypeScript 引用资源文件后提示找不到的异常处理技巧
2020/07/15 Javascript
使用eslint和githooks统一前端风格的技巧
2020/07/29 Javascript
JS hasOwnProperty()方法检测一个属性是否是对象的自有属性的方法
2021/01/29 Javascript
JavaScript代码实现微博批量取消关注功能
2021/02/05 Javascript
[42:32]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第二场 11.27
2020/12/01 DOTA
Python实现多行注释的另类方法
2014/08/22 Python
python 爬虫出现403禁止访问错误详解
2017/03/11 Python
Python中*args和**kwargs的区别详解
2019/09/17 Python
python orm 框架中sqlalchemy用法实例详解
2020/02/02 Python
Glamest意大利:女性在线奢侈品零售店
2019/04/28 全球购物
匈牙利超级网上商店和优惠:Alza.hu
2019/12/17 全球购物
C#如何调用Windows程序打开一个文档
2014/12/26 面试题
大学校园毕业自我鉴定
2014/01/15 职场文书
迎新晚会邀请函
2014/02/01 职场文书
项目投资意向书
2014/04/01 职场文书
请假条范文大全
2014/04/10 职场文书
优秀三好学生事迹材料
2014/08/31 职场文书
支行行长竞聘报告
2014/11/06 职场文书
教师个人事迹材料
2014/12/17 职场文书
财务部岗位职责
2015/02/03 职场文书
先进工作者个人总结
2015/02/15 职场文书
社区法制宣传月活动总结
2015/05/07 职场文书
2016五四青年节活动总结范文
2016/04/06 职场文书