低版本:

 #!/usr/bin/env python
import threading
import time
import queue class TreadPool:
"""
将线程加入到队列中作为资源去完成任务
优点:简单好写容易理解
缺点:太尼玛多了.....
"""
def __init__(self, maxsize):
self.maxsize = maxsize
self._q = queue.Queue(maxsize)
for i in range(maxsize):
self._q.put(threading.Thread) def get_thread(self):
return self._q.get() def add_thread(self):
self._q.put(threading.Thread) def task(arg, p):
print(arg)
time.sleep(1)
p.add_thread() pool = TreadPool(5) for i in range(100):
t = pool.get_thread()
obj = t(target=task, args=(i, pool))
obj.start()

高级版本:

 #!/usr/bin/env python
# -*- coding:utf-8 -*- import queue # 队列模块
import threading # 线程模块
import contextlib # 上下文模块
import time # 时间模块 StopEvent = object() # 创建一个停止时所需要用到的对象 class ThreadPool(object):
"""
线程池(用于放置任务,将任务作为队列中元素让线程去取得,可以复用线程减少开销)
"""
def __init__(self, max_num, max_task_num=None):
"""
构造方法
:param max_num:
:param max_task_num:所创建的队列内最大支持的任务个数
"""
if max_task_num:
self.q = queue.Queue(max_task_num) # 指定队列任务数量则创建有限队列
else:
self.q = queue.Queue() # 未指定队列任务数量则创建无限队列
self.max_num = max_num # 每次使用的最大线程个数
self.cancel = False # 任务取消,默认False,用于线程停止的判断
self.terminal = False # 任务终止,默认False,用于线程池终止的判断
self.generate_list = [] # 定义一个已生成任务列表
self.free_list = [] # 定义一个空闲任务列表 def run(self, func, args, callback=None):
"""
线程池执行一个任务方法
:param func: 传递进来的任务函数
:param args: 任务函数使用的参数
:param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数
1、任务函数执行状态;
2、任务函数返回值(默认为None,即:不执行回调函数)
:return: 如果线程池已经终止,则返回True否则None
"""
if self.cancel: # 如果条件为真则不会继续执行
return
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread() # 如果现有空闲列表无元素并且已生成任务列表内
# 元素个数小于队列支持的最大数量则创建一个线程
w = (func, args, callback,) # 具体任务
self.q.put(w) # 将任务放入队列当中 def generate_thread(self):
"""
创建一个线程方法
"""
t = threading.Thread(target=self.call) # 调用线程类创建一个线程,参数传递self.call方法
t.start() # 线程开始 def call(self):
"""
循环去获取任务函数并执行任务函数
"""
current_thread = threading.currentThread() # 创建当前任务
self.generate_list.append(current_thread) # 生成任务列表添加当前任务 event = self.q.get() # 事件获取
while event != StopEvent: # 当前事件不是停止时执行 func, arguments, callback = event # 任务具体函数,参数获取
try:
result = func(*arguments) # 结果为任务处理的出的结果
success = True # 任务处理成功
except Exception as e:
success = False # 任务处理失败
result = None # 结果为None if callback is not None: # 回调不为空
try:
callback(success, result) # 将刚才执行结果返回
except Exception as e:
pass with self.worker_state(self.free_list, current_thread):
if self.terminal: # 如果线程池已经被终止
event = StopEvent # 事件变为空任务
else:
event = self.q.get() # 事件为正常任务
else: self.generate_list.remove(current_thread) # 生成任务列表移除当前任务 def close(self):
"""
执行完所有的任务后,所有线程停止
"""
self.cancel = True # 线程停止,判定条件变为真
full_size = len(self.generate_list) # 获取还有几个在执行任务的线程
while full_size: # 向队列中添加相应个数的空任务
self.q.put(StopEvent)
full_size -= 1 def terminate(self):
"""
无论是否还有任务,终止线程
"""
self.terminal = True # 线程池关闭,判定条件变为真 while self.generate_list: # 当还有线程存在时放置空任务
self.q.put(StopEvent) self.q.queue.clear() # 将队列中所有任务清空 @contextlib.contextmanager
def worker_state(self, state_list, worker_thread):
"""
用于记录线程中正在等待的线程数
"""
state_list.append(worker_thread) # 等待状态列表中添加正在等待的线程数
try:
yield
finally:
state_list.remove(worker_thread) # 移除正在等待的线程数 # How to use pool = ThreadPool(5) # 创建一个每次支持5线程的线程池 def callback(status, result):
# status, execute action status
# result, execute action return value
pass def action(i): # 任务函数
print(i) for i in range(30): # 使用线程池执行30次任务
ret = pool.run(action, (i,), callback) time.sleep(1) # 1秒等待
print(len(pool.generate_list), len(pool.free_list)) # 打印线程池内当前任务个数及空任务个数
pool.close() # 线程停止
pool.terminate() # 线程池终止

python第十一天-----补:线程池的更多相关文章

  1. Python SSH爆破以及Python3线程池控制线程数

    源自一个朋友的要求,他的要求是只爆破一个ip,结果出来后就停止,如果是爆破多个,完全没必要停止,等他跑完就好 #!usr/bin/env python #!coding=utf-8 __author_ ...

  2. Python之实现不同版本线程池

    1.利用queue和threading模块可以实现多个版本的线程池,这里先贴上一个简单的 import queue import time import threading class ThreadP ...

  3. python第五课——自定义线程池

    内容概要: 1.low版线程池 2.绝版线程池 1.low版线程池 设计思路:运用队列queue 将线程类名放入队列中,执行一个就拿一个出来 import queue import threading ...

  4. 并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)

    史上最清晰的线程池源码分析 鼎鼎大名的线程池.不需要多说!!!!! 这篇博客深入分析 Java 中线程池的实现. 总览 下图是 java 线程池几个相关类的继承结构:    先简单说说这个继承结构,E ...

  5. Java并发(二十一):线程池实现原理

    一.总览 线程池类ThreadPoolExecutor的相关类需要先了解: (图片来自:https://javadoop.com/post/java-thread-pool#%E6%80%BB%E8% ...

  6. Python中为什么要使用线程池?如何使用线程池?

    系统处理任务时,需要为每个请求创建和销毁对象.当有大量并发任务需要处理时,再使用传统的多线程就会造成大量的资源创建销毁导致服务器效率的下降.这时候,线程池就派上用场了.线程池技术为线程创建.销毁的开销 ...

  7. 《Windows核心编程系列》十一谈谈Windows线程池

    Windows线程池 上一篇博文我们介绍了IO完成端口.得知IO完成端口可以非常智能的分派线程.但是IO完成端口仅对等待它的线程进行分派,创建和销毁线程的工作仍然需要我们自己来做. 我们自己也可以创建 ...

  8. Java并发编程的艺术(十一)——Executor与线程池

    Executor框架简介 从JDK5开始,把工作单元和执行机制分离开来了,工作的单元包括Runnable和Callable,执行机制就是由Executor框架提供. Executor两级调度模型 Ho ...

  9. python第十一天-----补:缓存操作

    memcached,首先下载python-memcached模块,在cmd中执行pip install python-memcached即可 memcached比较简单,默认情况仅支持简单的kv存储, ...

随机推荐

  1. Github 笔记

    在本地创建并切换 git checkout -b your_branch_name 把本地分支的修改提交到远端的分支上 git push origin local_branch_name:remote ...

  2. Java--RuntimeException(运行时异常)

    [转载自]:http://blog.csdn.net/qq7342272/article/details/7940741 java运行时异常是可能在java虚拟机正常工作时抛出的异常. java提供了 ...

  3. testNG中同一个test节点上class的执行顺序

    如果每个class中都有setUp(),那么先执行所有class的setUp方法,之后再执行具体的测试方法.这样就导致只有最后一个测试能通过,其他测试都失败了. 具体设置如下图:

  4. java 里面的string 和byte[] 怎么互转

    public class TestBytes { private static String FORMAT = "UTF-8"; public static void main(S ...

  5. 三线程连续打印ABC

    package test5; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Reentr ...

  6. 用JavaScript动态加载CSS和JS文件

    本文转载自:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/11/14/2248451.html 今天项目中需要用到动态加载 CSS 文件 ...

  7. Android学习笔记(二)

    Google在Android4.0之后加入了Action Bar的功能.但是有时候标题栏会相当占用屏幕空间,使得内容区域变小,这里演示如何隐藏标题栏. 隐藏标题栏的方法很简单,打开上节的FirstAc ...

  8. php 读取文件readfile

    <?php //读取文件 //echo readfile('aa.txt'); //打开文件更好的方法是fopen $f = fopen('aa.txt' , 'r') or die('unab ...

  9. 使用gson解析,生成Json

    包:gson-2.3.jarJson文本解析为Java对象:Java对象生成为Json文本 import com.google.gson.Gson; public class TestGson { c ...

  10. shell 初学者 必读 ,强烈推荐新手读

    背景: 很多人从C/C++转化而来,看了学习文档之后,踩入了很多坑 1 对变量赋值 不要有空格 a=123 # 正确 a = 123 # 错误 2  if语句 [] 要留有空格,变量最好加" ...