用Python实现一个简单的线程池


Posted in Python onApril 07, 2015

线程池的概念是什么?

在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是 如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些 很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。

我理解为线程池是一个存放很多线程的单位,同时还有一个对应的任务队列。整个执行过程其实就是使用线程池中已有有限的线程把任务 队列中的任务做完。这样做的好处就是你不需要为每个任务都创建一个线程,因为当你创建第100个线程来执行第100个任务的时候,可能前面已经有50个线 程结束工作了。因此重复利用线程来执行任务,减少系统资源的开销。

一个不怎么恰当的比喻就是,有100台电脑主机箱需要从1楼搬到2楼,你不需要喊来100人帮忙搬,你只需要叫十个或者二十个人就足以,每个人分配十个或者五个甚至是谁搬的快谁就多搬知道完成未知。(这个比喻好像。。。。。)

不管如何吧,大体上理解了线程池的概念。那么怎么用python实现呢?

代码如下
 

# !/usr/bin/env python
# -*- coding:utf-8 -*-
# ref_blog:http://www.open-open.com/home/space-5679-do-blog-id-3247.html
import Queue
import threading
import time
class WorkManager(object):
  def __init__(self, work_num=1000,thread_num=2):
    self.work_queue = Queue.Queue()
    self.threads = []
    self.__init_work_queue(work_num)
    self.__init_thread_pool(thread_num)
  """
    初始化线程
  """
  def __init_thread_pool(self,thread_num):
    for i in range(thread_num):
      self.threads.append(Work(self.work_queue))
  """
    初始化工作队列
  """
  def __init_work_queue(self, jobs_num):
    for i in range(jobs_num):
      self.add_job(do_job, i)
  """
    添加一项工作入队
  """
  def add_job(self, func, *args):
    self.work_queue.put((func, list(args)))#任务入队,Queue内部实现了同步机制
  """
    检查剩余队列任务
  """
  def check_queue(self):
    return self.work_queue.qsize()
  """
    等待所有线程运行完毕
  """ 
  def wait_allcomplete(self):
    for item in self.threads:
      if item.isAlive():item.join()
class Work(threading.Thread):
  def __init__(self, work_queue):
    threading.Thread.__init__(self)
    self.work_queue = work_queue
    self.start()
  def run(self):
    #死循环,从而让创建的线程在一定条件下关闭退出
    while True:
      try:
        do, args = self.work_queue.get(block=False)#任务异步出队,Queue内部实现了同步机制
        do(args)
        self.work_queue.task_done()#通知系统任务完成
      except Exception,e:
        print str(e)
        break
#具体要做的任务
def do_job(args):
  print args
  time.sleep(0.1)#模拟处理时间
  print threading.current_thread(), list(args)
if __name__ == '__main__':
  start = time.time()
  work_manager = WorkManager(10, 2)#或者work_manager = WorkManager(10000, 20)
  work_manager.wait_allcomplete()
  end = time.time()
  print "cost all time: %s" % (end-start)

这个代码清晰易懂。

整个代码只有两个类:WorkManager和Work,前者确实如命名所示,是一个管理者,管理线程池和任务队列,而后者就是具体的一个线程。

它的整个运行逻辑就是,给WorkManager分配制定的任务量和线程数,然后每个线程都从任务队列中获取任务来执行,直到队列中没有任务。这里面也用到了Queue内部的同步机制(至于是啥同步机制目前还没去研究)。

总结一下这样一个线程池的作用,对于我本来的目的其实这个东西是永不上的,因为我需要在web页面来控制线程的启动和停止,而这个线程池看起来只是用来并发完任务的。不过我想虽然在控制线程方面没有作用,但是它的并发执行任务的作用还是蛮不错,或许可以用在爬网页的部分。

Python 相关文章推荐
写了个监控nginx进程的Python脚本
May 10 Python
一篇文章入门Python生态系统(Python新手入门指导)
Dec 11 Python
详解Python里使用正则表达式的ASCII模式
Nov 02 Python
Python批量合并有合并单元格的Excel文件详解
Apr 05 Python
Python控制键盘鼠标pynput的详细用法
Jan 28 Python
深入解析神经网络从原理到实现
Jul 26 Python
django与vue的完美结合_实现前后端的分离开发之后在整合的方法
Aug 12 Python
python爬虫 爬取超清壁纸代码实例
Aug 16 Python
python3中pip3安装出错,找不到SSL的解决方式
Dec 12 Python
Python基于codecs模块实现文件读写案例解析
May 11 Python
python四种出行路线规划的实现
Jun 23 Python
详解OpenCV曝光融合
Apr 29 Python
浅谈Python程序与C++程序的联合使用
Apr 07 #Python
浅要分析Python程序与C程序的结合使用
Apr 07 #Python
python实现根据用户输入从电影网站获取影片信息的方法
Apr 07 #Python
python中列表元素连接方法join用法实例
Apr 07 #Python
简单介绍Python中的filter和lambda函数的使用
Apr 07 #Python
解析Python中的变量、引用、拷贝和作用域的问题
Apr 07 #Python
在Python中利用Pandas库处理大数据的简单介绍
Apr 07 #Python
You might like
php更改目录及子目录下所有的文件后缀的代码
2010/09/24 PHP
php 记录进行累加并显示总时长为秒的结果
2011/11/04 PHP
Yii 2.0中场景的使用教程
2017/06/02 PHP
深入解析Laravel5.5中的包自动发现Package Auto Discovery
2017/09/13 PHP
PHP强制转化的形式整理
2020/05/22 PHP
jquery 图片预加载 自动等比例缩放插件
2008/12/25 Javascript
JS 实现导航栏悬停效果(续2)
2013/09/24 Javascript
jquery中插件实现自动添加用户的具体代码
2013/11/15 Javascript
JS获取select-option-text_value的方法
2013/12/26 Javascript
JQuery显示隐藏DIV的方法及代码实例
2015/04/16 Javascript
Jquery实现动态切换图片的方法
2015/05/18 Javascript
在Node.js应用中使用Redis的方法简介
2015/06/24 Javascript
JS简单循环遍历json数组的方法
2016/04/22 Javascript
微信小程序 地图(map)实例详解
2016/11/16 Javascript
canvas实现图像布局填充功能
2017/02/06 Javascript
详解JS构造函数中this和return
2017/09/16 Javascript
webpack项目轻松混用css module的方法
2018/06/12 Javascript
获取layer.open弹出层的返回值方法
2018/08/20 Javascript
Vue $emit $refs子父组件间方法的调用实例
2018/09/12 Javascript
React中获取数据的3种方法及优缺点
2020/02/18 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
python基于windows平台锁定键盘输入的方法
2015/03/05 Python
python使用正则表达式匹配字符串开头并打印示例
2017/01/11 Python
如何安装多版本python python2和python3共存以及pip共存
2018/09/18 Python
python try...finally...的实现方法
2020/11/25 Python
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
伦敦著名的运动鞋综合商店:Footpatrol
2019/03/25 全球购物
仓库保管员岗位职责
2013/12/20 职场文书
工商治理实习生的自我评价
2014/01/15 职场文书
2014年班主任工作总结
2014/11/08 职场文书
田径运动会通讯稿
2015/07/18 职场文书
2016年小学中秋节活动总结
2016/04/05 职场文书
MySQL系列之四 SQL语法
2021/07/02 MySQL
Canvas如何做个雪花屏版404的实现
2021/09/25 HTML / CSS
python模块与C和C++动态库相互调用实现过程示例
2021/11/02 Python
jdbc中自带MySQL 连接池实践示例
2022/07/23 MySQL