Python线程进程[event,队列,进程[未完]]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python线程进程[event,队列,进程[未完]]相关的知识,希望对你有一定的参考价值。
Event:
由于每个线程都是独立运行的,但是如果某个线程的运行需要通过另一个线程的运行状态来进行自己的下一步运行操作时。这时就需要event对象来支持这种操作了。它运行线程等待某些时间的发生,初始对象中的信号标志被设置为False。如果有一个线程在等待一个Event对象,如果信号标志位一直是False ,那这个线程会一直等下去直至信号标志变为True。如果信号标志原本就是True,线程就会忽略这个设置继续运行。
用法:
event.isSet():返回event的状态值; event.wait():如果 event.isSet()==False将阻塞线程; event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度; event.clear():恢复event的状态值为False。
示例:
import threading,time event=threading.Event() #创建对象 def foo(): while not event.is_set(): #如果event为False状态,那么就循环每两秒打印一次event的状态 print("wait......") event.wait(2) #括号内如果可以写数字 单位为秒,表示不管信号标志有没有变为True,只要等待2秒后就继续运行 #event.wait() # if event对象内的标志位为False,阻塞,默认为False print("Connect to redis server") for i in range(5): t=threading.Thread(target=foo,args=()) #创建五个线程 t.start() #启动线程 print("attempt to start redis server") time.sleep(6) #暂停主进程 6秒 event.set() # 设置标志位为True
队列:
类似列表的数据结构,内部自带锁保证线程安全的数据结构。
分类:
先进先出
先进后出
import queue q = queue.Queue(3) #先进先出 FIFO q = queue.Queue(3) #数字3表示队列中最多有3个值,如果超出 3个则等队列中被取出一个数据后在put print(q) q.put(11) #添加数据进入队列 q.put(‘hello‘) q.put(54.2) q.put(68879879) print(q.get()) q.put(979879) print(q.get()) #取出数据 print(q.get()) print(q.get()) print(q.get()) q.join() #阻塞进程 直到所有任务完成,需要配合 task_done()使用 import threading def foo(): q.put(11111111) q.put(222222) #向队列传入数据 q.put(33333333) q.join() #例如这里传入队列有是哪个数据,那么join只有在接收到三个task_done的时候才会认为任务完成。 print(‘ok‘) def bar(): print(q.full()) #队列是够满 print(q.qsize()) #队列长度 print(q.get()) #获取队列数据 # q.task_done() print(q.get()) # q.task_done() print(q.get()) # q.task_done() print(q.qsize()) q.task_done() q.task_done() #发送三次 task_done q.task_done() t1 = threading.Thread(target=foo,args=()) #开两个进程 一个向队列传入数据,一个从队列取出数据 t2 = threading.Thread(target=bar,args=()) t1.start() t2.start() 先进后出 import queue q = queue.LifoQueue() #后进后出(先进后出) q.put(1) #出入数据 q.put(2) q.put(3) while not q.empty(): #如果不 print(q.get())
按顺序输出: import queue q = queue.PriorityQueue() q.put([1,"1111"]) # 如果是列表形式,则会从左到右进行比较,例如这里:列表第一位是数字,则按照 0-9的顺讯进行排序,如果存在相同的数,则比对后面的数值先后顺序为 字符串0-9 a-z
#中文的话,先把中文传换成字节,然后进行比对 顺序同ascii一样
q.put([5,‘22222222‘]) q.put([8,‘3333333‘]) q.put([3,‘44444444‘]) 优先级按照ascii码的大小规则进行比较 q.put(‘a‘) q.put(‘v‘) q.put(‘c‘) q.put(‘1555‘) q.put(‘777‘) while not q.empty(): #如果队列不为空就循环取出队列中的消息 print(q.get())
"生产者"和"消费者":
生产者消费模型通过一个容器来解决生产者和消费者之间的耦合文件,生产者和消费者之间不直接通讯,而是通过队列来进行通讯,所以生产者生产数据不需要等待消费者处理,直接放进队列中,消费者直接取队列中取出数据。
生产者:创建数据的模型
消费者:消费数据的模型
示例:
import queue,threading,time import random q=queue.Queue() def Producer(): #创建一个厨师对象 count=1 while count<10: #做包子 每做一个就加入队列中 if q.qsize()<20: #如果队列中的包子不超过20个就继续做 s=random.randint(1,100) q.put(s) print(" has made baozi %s"%s) time.sleep(1) #睡一秒 count+=1 #计数器加一 def Consumer(id): #消费者 while 1: #消费者一直取包子,每取一个包子就 sleep2秒 s=q.get() print("Consumer"+id+"has eat %s"%s) time.sleep(2) for i in range(5): #一次五个厨师(线程)同时做包子 t1=threading.Thread(target=Producer,args=()) t1.start() for i in range(2): #每次来两个客人(线程)取出包子 t=threading.Thread(target=Consumer,args=(str(i),)) t.start()
进程:
multiprocessing模块:
通过multiprocessing模块我们可以创建多个子进程来运行程序,达到计算密集型程序的加速计算目的。可以利用多个cpu核心同时计算。弥补Python中线程的不足。但是进程的切换远比线程复杂,所以能不用进程就不要用进程
多进程:
优点:
利用多核,实现并行运算
缺点:
1.开销太大
2.通信困难
#实验下列计算时间
import multiprocessing import time def foo(n): #计算加法和 ret=0 for i in range(n): ret+=i print(ret) def bar(n): #计算乘法 ret=1 for i in range(1,n): ret*=i print(ret) if __name__ == ‘__main__‘: #Windows 创建 进程必须在 process下创建 s=time.time() # # foo(100000000) #一个一个计算,耗时很久 # bar(100000) p1 = multiprocessing.Process(target=foo,args=(100000000,)) #使用多进程方式计算 需要的时间远远小于 一个一个的计算方式 p1.start() p2 = multiprocessing.Process(target=bar,args=(100000,) ) #进程普通使用方式跟线程类似 p2.start() p1.join() p2.join() print(time.time()-s)
进程的PID:
from multiprocessing import Process #调用process模块 import os def info(name): print("name:",name) print(‘parent process:‘, os.getppid()) #查看父进程 pid print(‘process id:‘, os.getpid()) #查看子进程 pid print("------------------") if __name__ == ‘__main__‘: #Windows下进程创建必须在 if __name__ 下创建要不会出错 p1 = Process(target=info, args=(‘Process Test‘,)) #实例化进程 p1.start() #启动进程 p1.join()
以上是关于Python线程进程[event,队列,进程[未完]]的主要内容,如果未能解决你的问题,请参考以下文章
Python开发基础-Day31 Event对象队列和多进程基础