python多线程+生产者和消费者模型+queue使用
多线程简介
多线程:在一个进程内部,要同时干很多事情,就需要同时执行多个子任务,我们把进程内的这些子任务叫线程。
线程的内存空间是共享的,每个线程都共享同一个进程的资源
模块:
1、_thread模块 低级模块(在python3里基本已弃用)
2、threading模块 高级模块 对_thread模块进行了封装
threading模块使用
1.使用元组传递 threading.Thread(target=方法名,arg=(参数1,参数2...))
2.用字典传递 threading.Thread(target=方法名,kwargs={“参数名”:参数1,“参数名”:参数2,....})
3.混合使用元组和字典 threading.Thread(target=方法名,args=(参数1,参数2,...),kwargs={“参数名”:参数1,“参数名”:参数2,....})
4.查看线程数:
使用threading.enumerate()函数便可以看到当前线程的数量。
5.查看当前线程的名字:
使用threading.current_thread()可以看到当前线程的信息。
6.join([time]):等待至线程终止。这阻塞调用线程直至线程的join()方法被调用终止、正常退出或者抛出未处理的异常、或者是可选的超时发生。
7.isAlive():返回线程是否活动
8.getName(): 返回线程名
9.setNmae():设置线程名
10.后台线程(守护线程)
后台线程有一个特征:如果所有的前台线程都死亡了,那么后台线程也会自动死亡。
调用Thread对象的daemon属性可将指定线程设置为后台线程。在下面程序可以看到程序里的线程被指定为后台线程,当所有前台程序都死亡了后,后台线程随之死亡。当在整个虚拟机里只剩下后台线程时,程序就没有继续运行的必要了,所以程序也就退出了。
import threading
# 定义后台线程的线程执行体与普通线程没有任何区别
def action(max):
for i in range(max):
print(threading.current_thread().name + " " + str(i))
t = threading.Thread(target=action, args=(100,), name='后台线程')
# 将此线程设置成后台线程
# 也可在创建Thread对象时通过daemon参数将其设为后台线程
t.daemon = True
# 启动后台线程
t.start()
for i in range(10):
print(threading.current_thread().name + " " + str(i))
# -----程序执行到此处,前台线程(主线程)结束------
# 后台线程也应该随之结束
上面程序中的粗体字代码先将t线程设置成后台线程,然后启动该线程。本来该线程应该执行到i等于99时才会结束,但在运行程序时不难发现,该后台线程无法运行到99,因为当主线程也就是程序中唯一的前台线程运行结東后,程序会主动退出,所以后台线程也就被结東了。从上面的程序可以看出,主线程默认是前台线程,t线程默认也是前台线程。但并不是所有的线程默认都是前台线程,有些线程默认就是后台线程一一前台线程创建的子线程默认是前台线程,后台线程创建的子线程默认是后台线程
可见,创建后台线程有两种方式。
- 主动将线程的 daemon属性设置为True
- 后台线程启动的线程默认是后台线程。
以下看一个简单的多线程程序:
import threading
import time
def coding():
for x in range(3):
print('%s正在写代码' % x)
time.sleep(1)
def drawing():
for x in range(3):
print('%s正在画图' % x)
time.sleep(1)
def single_thread():
coding()
drawing()
def multi_thread():
t1 = threading.Thread(target=coding)
t2 = threading.Thread(target=drawing)
t1.start()
t2.start()
if __name__ == '__main__':
multi_thread()
继承自threading.Thread类:
为了让线程代码更好的封装。可以使用threading模块下的Thread类,继承自这个类,然后实现run方法,线程就会自动运行run方法中的代码。示例代码如下:
import threading
import time
class CodingThread(threading.Thread):
def run(self):
for x in range(3):
print('%s正在写代码' % threading.current_thread())
time.sleep(1)
class DrawingThread(threading.Thread):
def run(self):
for x in range(3):
print('%s正在画图' % threading.current_thread())
time.sleep(1)
def multi_thread():
t1 = CodingThread()
t2 = DrawingThread()
t1.start()
t2.start()
if __name__ == '__main__':
multi_thread()
start()和run()
start()
start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。run()
run()
run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
记住:多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发。start() 和 run()的区别说明
start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
run() : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!
Lock版本生产者和消费者模型
生产者和消费者模式是多线程开发中经常见到的一种模式。生产者的线程专门用来生产一些数据,然后存放到一个中间的变量中。消费者再从这个中间的变量中取出数据进行消费。但是因为要使用中间变量,中间变量经常是一些全局变量,因此需要使用锁来保证数据完整性。以下是使用threading.Lock锁实现的“生产者与消费者模式”的一个例子:
import threading
import random
import time
gMoney = 1000
glo = threading.Lock()
gTotaltime = 10
gTime = 0
class Consumer(threading.Thread):
def run(self):
global gMoney
global gTime
while True:
money = random.randint(100,1000)
glo.acquire()
if gMoney>= money:
gMoney -= money
print("{}消费了{}元,当前剩余{}元".format(threading.current_thread(),money,gMoney))
else:
print("{}准备消费{}元,当前剩余{}元,不足,不能消费".format(threading.current_thread(),money,gMoney))
if gTime >= gTotaltime and money > gMoney:
glo.release()
break
glo.release()
time.sleep(0.7)
class Porducer(threading.Thread):
def run(self):
global gMoney
global gTime
while True:
Money = random.randint(100,700)
glo.acquire()
if gTime == gTotaltime:
glo.release()
break
gMoney += Money
print("{}生产了{}元钱,剩余{}元钱".format(threading.current_thread(),Money,gMoney))
gTime += 1
glo.release()
time.sleep(0.5)
def main():
for x in range(3):
t1 = Porducer(name="生产者")
t1.start()
for i in range(5):
t = Consumer(name="消费者")
t.start()
if __name__ == '__main__':
main()
queue线程安全队列
在线程中,访问一些全局变量,加锁是一个经常的过程。如果你是想把一些数据存储到某个队列中,那么Python内置了一个线程安全的模块叫做queue模块。Python中的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先进先出)队列Queue,LIFO(后入先出)队列LifoQueue。这些队列都实现了锁原语(可以理解为原子操作,即要么不做,要么都做完),能够在多线程中直接使用。可以使用队列来实现线程间的同步。相关的函数如下:
- 初始化Queue(maxsize):创建一个先进先出的队列。
- qsize():返回队列的大小。
- empty():判断队列是否为空。
- full():判断队列是否满了。
- get():从队列中取最后一个数据。
- put(item,block=Ture,timeout=None):将一个数据放到队列中。如果队列已满,且block参数为Ture(阻塞),当前线程被阻塞,timeout指定阻塞时间,如果将timeout设置为None,则代表一直阻塞,直到有元素被放入队列中:如果队列已空,且block参数设置为False(不阻塞),则直接引发queue.Empty异常。
下面就可以用queue来进行线程通信
import queue
import time
import threading
def set_value(q):
index = 0
while True:
q.put(index)
index += 1
time.sleep(3)
def get_value(q):
index = 0
while True:
print(q.get())
time.sleep(0.5)
def main():
q = queue.Queue(4)
t1 = threading.Thread(target=set_value,args=[q])
t2 = threading.Thread(target=get_value,args=[q])
t1.start()
t2.start()
if __name__ == '__main__':
main()
python多线程+生产者和消费者模型+queue使用的更多相关文章
- Python之生产者&、消费者模型
多线程中的生产者和消费者模型: 生产者和消费者可以用多线程实现,它们通过Queue队列进行通信. import time,random import Queue,threading q = Queue ...
- python:生产者与消费者模型
1,生产者与消费者模型的矛盾在于数据供需的不平衡 import time import random from multiprocessing import Queue from multiproce ...
- 生产者、消费者模型---Queue类
Queue队列在几乎每种编程语言都会有,python的列表隐藏的一个特点就是一个后进先出(LIFO)队列.而本文所讨论的Queue是python标准库queue中的一个类.它的原理与列表相似,但是先进 ...
- python queue和生产者和消费者模型
queue队列 当必须安全地在多个线程之间交换信息时,队列在线程编程中特别有用. class queue.Queue(maxsize=0) #先入先出 class queue.LifoQueue(ma ...
- Python 之并发编程之进程下(事件(Event())、队列(Queue)、生产者与消费者模型、JoinableQueue)
八:事件(Event()) # 阻塞事件: e = Event() 生成事件对象e e.wait() 动态给程序加阻塞,程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值 ...
- Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
- 人生苦短之我用Python篇(队列、生产者和消费者模型)
队列: queue.Queue(maxsize=0) #先入先出 queue.LifoQueue(maxsize=0) #last in fisrt out queue.PriorityQueue( ...
- python并发编程之守护进程、互斥锁以及生产者和消费者模型
一.守护进程 主进程创建守护进程 守护进程其实就是'子进程' 一.守护进程内无法在开启子进程,否则会报错二.进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束 守护进程简单实例: fr ...
- 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型
关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...
随机推荐
- [工具-005] C#如何绑定HotKey
由于某种需要,需要做一个控制鼠标在屏幕乱点的程序,运用C#的 [DllImport("user32.dll")] private static extern int mo ...
- java1.8时间处理
object TimeUtil { var DEFAULT_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss") var H ...
- 01Java核心-冷门知识001-包
1)导入静态方法和静态域 import 可以加上static关键字,导入静态的方法和静态域. 例如: package com.gail.test; import static java.lang.Sy ...
- 关于thisState的那些事
1.state的定义 状态(state) 和 属性(props) 类似,都是一个组件所需要的一些数据集合,但是它是私有的,并且由组件本身完全控制,可以认为它是组件的“私有属性(或者是局部属性)”. 2 ...
- Rocket - tilelink - AsyncCrossing
https://mp.weixin.qq.com/s/v8plWCBD8vZkxykjJe4TCg 介绍AsyncCrossing的实现,主要介绍如何实现diplomacy Node和LazyMo ...
- 一文说通Dotnet Core的中间件
前几天,公众号后台有朋友在问Core的中间件,所以专门抽时间整理了这样一篇文章. 一.前言 中间件(Middleware)最初是一个机械上的概念,说的是两个不同的运动结构中间的连接件.后来这个概念 ...
- 关于MySQL无法启动的一点问题
今天早上做作业启动MySQL遇到服务无法启动的问题,在网上找方法解决找了一个钟. 修改host文件,重装mysql服务,就差卸载重装了.到后面终于找到问题,原来是我之前改了root密码,所以每次启动m ...
- Java实现 蓝桥杯VIP 算法训练 一元三次方程
问题描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...
- Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
算法提高 贪吃的大嘴 时间限制:1.0s 内存限制:256.0MB 问题描述 有一只特别贪吃的大嘴,她很喜欢吃一种小蛋糕,而每一个小蛋糕有一个美味度,而大嘴是很傲娇的,一定要吃美味度和刚好为m的小蛋糕 ...
- Mac上查看当前安卓手机上打开的app的包名和主程序入口
1.连接上手机,数据线链接或者无线连接随便 2.打开你需要查看的app 3.打开终端,输入命令: adb shell dumpsys window w |grep \/ |grep name=