python内置队列模块 queue

queue的四种队列

q = queue.Queue()           # 先进先出队列
q = queue.LifoQueue() # 后进先出队列
q = queue.PriorityQueue() # 优先级队列
q = queue.deque() # 双向队列

queue.Queue()先进先出队列

  • 基本使用方法
import queue

q = queue.Queue(maxsize=10)  # 创建一个先进先出的队列,maxsize为队列大小

q.put(11)       # 向队列添加数据
q.put(22, block=False) # 默认block=True,表示为阻塞状态,如果队列中已经满了,就一直处于阻塞(等待)状态,直到队列中有位置为止
# block=Flase,表示为非阻塞状态,当队列满了的时候直接报错 queue.Full
q.put(33, timeout=2) # timeout=2,当队列满了的时候,等待2秒,如果2秒后还是满的则报错 queue.Full print(q.qsize()) # 返回队列中当前的个数
print(q.empty()) # 查看队列是否为空,返回True表示为空,False表示不为空
print(q.full()) # 查看队列是否满了,返回True表示满了,False表示没满
q.get() # 从队列取数据,如果队列没有数据,一直处于阻塞状态,直到取到数据为止
q.get(timeout=2) # 取数据,timeout参考 q.put(timeout=2)
q.get_nowait() # 从队列取数据,不阻塞,调用 q.get(block=False)
  • join和task_done的组合
# 情景1   当队列中没有数据的时候该线程还是处于阻塞状态
import queue q = queue.Queue(maxsize=10) # 创建一个先进先出的队列,maxsize为队列大小 q.put("sss")
q.get() q.join() # 任务完成之后才结束,否则一直处于阻塞状态 # 情景2 当每次从队列取完数据,执行task_done方法后,才表示该任务结束了
import queue
q = queue.Queue(maxsize=10) # 创建一个先进先出的队列,maxsize为队列大小 q.put("sss")
q.put("sss")
q.put("sss") q.get()
q.task_done()
q.get()
q.task_done()
q.get()
q.task_done() q.join() # 任务完成之后才结束,否则一直处于阻塞状态()

queue.LifoQueue() 后进先出队列

  • 基本使用方法,该队列接继承先进先出队列,其他方法参考先进先出队列
import queue
q = queue.LifoQueue() # 创建一个后进先出的队列,该队列基础先进先出队列
q.put(123)
q.put(456)
value = q.get()
print(value)

queue.PriorityQueue() 优先级队列

  • 基本使用方法,该队列接继承先进先出队列,其他方法参考先进先出队列
import queue
q = queue.PriorityQueue()
q.put((1, "aaa"))
q.put((2, "bbb"))
q.put((3, "ccc"))
q.put((-100, "0000"))
value = q.get()
print(value)

queue.deque() 双向队列

  • 基本使用方法
q = queue.deque()
q.append("appendright") # 在队列右边添加一个元素
q.appendleft("appendleft") # 在队列左边添加一个元素
right_v = q.pop() # 在队列右边取出一个元素
left_v = q.popleft() # 在队列左边取出一个元素 print(right_v)
print(left_v)
  • 双向队列剩下的一些方法
clear()   				# 清空整个队列
count(value) # 查看value在队列中的次数
extend(iterable) # 在队列右侧添加一个可迭代的数据
extendleft(iterable) # 在队列左侧添加一个可迭代的数据
remove(value) # 删除队列中第一个value值
reverse() # 将队列进行反转
rotate()

多线程

基本使用

  • 创建多线程的两种模式

    • 使用threading.Thread创建多线程
    import threading
    
    def f1(arg):
    print(arg) t = threading.Thread(target=f1, args=[123,])
    t.start()
    • 通过自定义类创建多线程
    import threading
    
    def f2(arg):
    print(arg) class MyThread(threading.Thread): # 自定义类,并继承threading.Thread类
    def __init__(self, func, args):
    self.func = func
    self.args = args
    super(MyThread, self).__init__() def run(self): # run方法用来执行线程里面的func函数
    self.func(self.args) obj = MyThread(func=f2, args=123)
    obj.start()

线程锁 (Lock、RLock)

  • 在没有锁的情况下
import threading
import time NUM = 10 def func():
global NUM
NUM -= 1 time.sleep(2)
print(NUM) for i in range(10):
t = threading.Thread(target=func)
t.start() # 输出
0
0
0
0
0
0
0
0
0
0
  • 单个锁 (Lock)
import threading
import time NUM = 10 def func():
global NUM
lock.acquire() # 加锁
NUM -= 1 time.sleep(2)
print(NUM)
lock.release() # 解锁 lock = threading.Lock() # 创建锁的对象
for i in range(10):
t = threading.Thread(target=func)
t.start() # 输出
9
8
7
6
5
4
3
2
1
0
  • 多重锁 (RLock)
import threading
import time NUM = 10 def func():
global NUM
lock.acquire() # 加锁
NUM -= 1 time.sleep(2) lock.acquire() # 加锁
NUM += 3
time.sleep(1)
print(NUM)
lock.release() # 解锁
lock.release() # 解锁 lock = threading.RLock() # 创建锁的对象
for i in range(10):
t = threading.Thread(target=func)
t.start()

信号量(Semaphore)

同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

import threading
import time def func(i):
sem.acquire() # 加锁
time.sleep(1)
print(i)
sem.release() # 解锁 maxThread = 5 # 定义最大线程数
semaphore = threading.BoundedSemaphore(maxThread) # 创建信号量对象,同时最多允许5个线程运行
for i in range(10):
t = threading.Thread(target=func, args=[i,])
t.start()

事件 (event)

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
  • clear:将“Flag”设置为False
  • set:将“Flag”设置为True
import threading

def func(i):
print(i)
event.wait() # 阻塞状态,等待event的flag变为True
print(i+100) event = threading.Event() # 创建event对象
for i in range(10):
t = threading.Thread(target=func, args=[i,])
t.start() event.clear() # 将event的flag变为flase inp = input(">>")
if inp == "1":
event.set() # 将event的flag变为True

条件 (Condition)

使得线程等待,只有满足某条件时,才释放n个线程
import threading

def func(i):
print(i)
con.acquire() # 加锁
con.wait() # 阻塞,等待notify方法执行唤醒该线程
print(i+100)
con.release() # 释放锁 con = threading.Condition()
for i in range(10):
t = threading.Thread(target=func, args=[i,])
t.start() while True:
inp = input(">>")
if inp == "q":
break
con.acquire() # 加锁
con.notify(int(inp)) # 激活int(inp)个线程执行
con.release() # 释放锁

计时器

定时器,指定n秒后执行某操作,主线程不阻塞
import threading

def hello():
print("hello, world") t = threading.Timer(2, hello)
t.start()
print("xxx")

自定义线程池

import queue
import threading
import time class ThreadPool: # 创建线程池类 def __init__(self, maxsize=5):
self.maxsize = maxsize
self._q = queue.Queue(maxsize) # 默认添加5个类名到队列中
for i in range(maxsize):
self._q.put(threading.Thread) def get_thread(self):
"""
从队列中取出一个线程名
:return:
"""
return self._q.get() def add_thread(self):
"""
向线程中添加一个线程名
:return:
"""
self._q.put(threading.Thread) def task(arg):
print(arg)
time.sleep(1)
pool.add_thread() # 当该任务完成时,调用add_thread()方法向队列中添加一个线程名 pool = ThreadPool(5) # 实例化线程池对象
for i in range(100):
t = pool.get_thread() # 调用get_thread()方法从队列中获取多线程名
obj = t(target=task, args=[i,]) # 执行多线程,生成线程对象
obj.start() # 将线程运行,等待cpu调度

生产者消费者模型(队列)

多进程

基本使用

多进程数据共享的三种方法

  • queues.Queue
from multiprocessing import Process
from multiprocessing import queues
import multiprocessing def foo(i):
q.put(i)
print("say hi", i, q.qsize()) # mac下调qsize()会报错,可以看下qsize的源码 # if __name__ == '__main__': # 在windows下运行需要加这行,否则会报错
q = queues.Queue(20, ctx=multiprocessing)
for i in range(10):
p = Process(target=foo, args=(i,))
p.start()
  • Array
from multiprocessing import Process
from multiprocessing import Array def foo(i, arg):
arg[i] = i + 100
for item in arg:
print(item)
print("==================") # if __name__ == '__main__': # windows下需要加上这行,否则会报错
li = Array('i', 10)
for i in range(10):
p = Process(target=foo, args=(i, li,))
p.start()
  • Manager
from multiprocessing import Process
from multiprocessing import Manager
import time def foo(i, arg):
arg[i] = i + 100
print(arg.values()) # if __name__ == '__main__': # windows下需要添加这行,否则会报错 obj = Manager()
li = obj.dict()
for i in range(10):
p = Process(target=foo, args=(i, li,))
p.start()
# p.join() time.sleep(0.1) # 需要加个等待时间,否则主进程执行完毕之后就会将li关闭掉, 或者在上面加个join

进程锁

参考线程锁

进程池


from multiprocessing import Pool import time def f1(arg):
time.sleep(1)
print(arg) # if __name__ == '__main__': # 在windows下执行需要加上这行,否则会报错 pool = Pool(5)
for i in range(30):
# pool.apply(func=f1, args=(i,)) # 单进程模式
pool.apply_async(func=f1, args=(i,)) # pool.close() # 所有任务执行完毕,在进行关闭进程池
pool.terminate() # 立即关闭进程池
pool.join()
print("end")

协程

原理:利用一个线程,分解一个线程成为多个微线程,程序级别,跟系统没关系
  • greenlet # 在gevent的基础之上进行的封装
  • gevent
from gevent import monkey
monkey.patch_all() import gevent
import requests def f(url):
print("GET: %s" % url)
resp = requests.get(url)
data = resp.text
print("%d bytes received from %s" % (len(data), url)) gevent.joinall([
gevent.spawn(f, "http://www.python.org"),
gevent.spawn(f, "http://www.yahoo.com"),
gevent.spawn(f, "http://www.github.com"),
])

python学习之路-11 多线程、多进程、协程的更多相关文章

  1. Python学习之路14☞多线程与多进程

    一 进程与线程的概念 1.1 进程 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数 ...

  2. 多线程 多进程 协程 Queue(爬虫代码)

    快速理解多进程与多线程以及协程的使用场合和特点 首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运 ...

  3. Python并发编程二(多线程、协程、IO模型)

    1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...

  4. Python学习之路11☞异常处理

    一 错误和异常 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 de ...

  5. 深入浅析python中的多进程、多线程、协程

    深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...

  6. Python多进程、多线程、协程

    转载:https://www.cnblogs.com/huangguifeng/p/7632799.html 首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是C ...

  7. 也说性能测试,顺便说python的多进程+多线程、协程

    最近需要一个web系统进行接口性能测试,这里顺便说一下性能测试的步骤吧,大概如下 一.分析接口频率 根据系统的复杂程度,接口的数量有多有少,应该优先对那些频率高,数据库操作频繁的接口进行性能测试,所以 ...

  8. python 多进程,多线程,协程

    在我们实际编码中,会遇到一些并行的任务,因为单个任务无法最大限度的使用计算机资源.使用并行任务,可以提高代码效率,最大限度的发挥计算机的性能.python实现并行任务可以有多进程,多线程,协程等方式. ...

  9. python中多进程+协程的使用以及为什么要用它

    前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重.切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL, ...

随机推荐

  1. Spark Yarn-cluster与Yarn-client

    摘要 在Spark中,有Yarn-Client和Yarn-Cluster两种模式可以运行在Yarn上,通常Yarn-cluster适用于生产环境,而Yarn-Cluster更适用于交互,调试模式,以下 ...

  2. PHP设计模式笔记五:策略模式 -- Rango韩老师 http://www.imooc.com/learn/236

    策略模式 1.概述:策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式称为策略模式 例如:一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不 ...

  3. C#隐式执行CMD命令

    本文实现C#隐式执行CMD功能命令.下图是示例程序的主界面. 在命令文本框输入DOS命令,点击"Run"button.在以下的文本框中输出执行结果. 以下是程序的完整代码. 本程序 ...

  4. 在用EF新增对象存贮至数据库时汪报错,但数据库里没有新增数据

    大致的问题是这样的: 原来一直用存贮数据的方法是用的是:DBContext.AddToXXXX(),这个方法.在写代码的时候看到VS提示这个方法已失效,推荐使用DBContext.XXXX.AddOb ...

  5. js参数截取

    原代码: function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^& ...

  6. iOS之断点下载,使用NSURLSession简单封装

    最近公司需要做个文件管理的功能模块,刚交到博主手上时,头都大了.因为没做过这方面的东西,只好咬牙加班,并请教某位大神,指点了一下,清楚研究方向,找了网上大量资料,最后实现简单的封装. 上代码:.h文件 ...

  7. Array.prototype.sort()

    sort() 方法对数组的元素做原地的排序,并返回这个数组.默认按照字符串的Unicode码位点(code point)排序. 语法 arr.sort([compareFunction]) 参数 co ...

  8. Floyd最小环

    本文转自这里 最小环:从一个点出发,经过一条简单路径回到起点成为环.图的最小环就是所有环中长度最小的. 怎样求最小环呢? 1传统的解决方法(dijkstra):        任意一个最小环环的权值, ...

  9. hdfs-over-ftp安装与配置

    hdfs-over-ftp是一个开源,简单易用的实现了对HDFS系统的下载和上传功能的小工具.可以作为管理工具来使用,快捷方便. 1 安装jdk(1.6以上版本)并配置环境变量分别执行java -ve ...

  10. [转载]Git常用命令

    转载自: Git常用命令 Git配置 git config --global user.name "robbin" git config --global user.email & ...