python进阶(八)~~~队列和多进程

python进阶(八)~~~队列和多进程

2023年8月2日发(作者:)

python进阶(⼋)~~~队列和多进程⼀、队列Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先⼊先出)队列Queue,LIFO(后⼊先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使⽤。可以使⽤队列来实现线程间的同步。(maxsize=0) maxsize默认为0,不设置或设置为负数时,表⽰可接受的消息数量没有上限。常⽤⽅法:_done() 在完成⼀项⼯作之后,_done()函数向任务已经完成的队列发送⼀个信号。每个get()调⽤得到⼀个任务,接下来task_done()调⽤告诉队列该任务已经处理完毕。() 实际上意味着等到队列为空,再执⾏别的操作(item,block=True, timeout=None) 写⼊队列,block=True,Timeout=3 意味着等待3s,队列仍没有位置就报错;block=False 意思是不等待,队列如果满了直接报错;(block=True, timeout=None) 获取队列,block和timeout参数说明同上_nowait() 相当于(block=False),不等待_nowait() 相当于(block=False),不等待() 返回队列的⼤⼩() 如果队列为空,返回True,反之() 如果队列满了,返回True,反之False, 与 maxsize ⼤⼩对应from queue import Queue,LifoQueue,PriorityQueue#先⼊先出队列q1=Queue(masize=2)(1)(2)print(()) # 判断队列是否已满,返回Trueprint(()) # 返回当前队列元素的个数(3,block=False) # 向队列中加⼊值,不等待,直接报错。

()()print(()) # 判断队列是否为空,返回_done()() #等待队列任务全部完成再继续执⾏,与队列长度⽆关,队列中每⼀个任务执⾏完需调⽤task_done⽅法,所有任务完成后才会继续执⾏join()后⾯的代码使⽤队列解决100万的bug:耗时⽐加锁长from threading import Thread,Lockfrom queue import Queueq=Queue(maxsize=2)num=(num)def work1(): global num for i in range(1000000): () #读取队列中的值 num+=1

(num) #加⼊队列def work2():  global num for i in range(1000000): () num+=1

(num) #加⼊队列def main(): t1=Thread(target=work1) t2=Thread(target=work2) () () () () print(num)if __name__=='__main__': main()LifoQueue 后⼊先出队列: 继承了Queue,所有⽅法⽤法与Queue⼀样,仅仅是取出的顺序发⽣变化。

PriorityQueue 优先级队列: q=PriorityQueue () ((1,22)) 以元祖形式添加元素,前⾯为优先级,后⾯为元素。优先级越低,越先取出。⼆、进程1.什么是进程?⼀个程序运⾏起来后,代码+⽤到的资源 称之为进程,是系统进⾏资源分配和调度的基本单位,⼀个程序⾄少有⼀个进程。在当代⾯向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。我们⾃⼰在python⽂件中写了⼀些代码,这叫做程序,运⾏这个python⽂件的时候,这叫做进程。2.进程状态介绍  在了解其他概念之前,我们⾸先要了解进程的⼏个状态。在程序运⾏的过程中,由于被操作系统的调度算法控制,程序会进⼊⼏个状态:就绪,运⾏和阻塞。  (1)就绪(Ready)状态    当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可⽴即执⾏,这时的进程状态称为就绪状态。  (2)执⾏/运⾏(Running)状态当进程已获得处理机,其程序正在处理机上执⾏,此时的进程状态称为执⾏状态。  (3)阻塞(Blocked)状态正在执⾏的进程,由于等待某个事件发⽣⽽⽆法执⾏时,便放弃处理机⽽处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满⾜、等待信件(信号)等。    事件请求:input、sleep、⽂件输⼊输出、recv、accept等    事件发⽣:sleep、input等完成了    时间⽚到了之后有回到就绪状态,这三个状态不断的在转换。3.进程,线程对⽐  功能:进程,能够完成多任务,⽐如 在⼀台电脑上能同时运⾏多个软件线程,能够完成多任务,⽐如⼀个QQ中的多个聊天窗⼝  定义:进程是系统进⾏资源分配和调度的⼀个独⽴单位线程是进程的⼀个实体,是CPU调度和分配的基本单位,它是⽐进程更⼩的能独⽴的基本单位,线程⾃⼰基本上不拥有系统资源,只拥有⼀点在运⾏中必不可少的资源(如程序计数器,⼀组寄存器和栈),但是它可与同属⼀个进程的其他线程共享所拥有的全部资源  区别:⼀个程序⾄少有⼀个进程,⼀个进程⾄少有⼀个线程线程的划分尺度⼩于进程(资源⽐进程少),使得多线程程序并发性⾼进程在执⾏过程中拥有独⽴的内存单元,⽽多个线程共享内存,从⽽极⼤地提⾼了程序的运⾏效率线程不能够独⽴执⾏,必须依存在进程中可以将进程理解为⼯⼚中的⼀条流⽔线,⽽线程就是流⽔线上的⼯⼈  优缺点:线程执⾏开销⼩,但不利于资源的管理和保护;进程正相反from multiprocessing import Processimport timedef work1(): for i in range(6): (1) print(f'第{i+1}次浇花中')def work2(name): for i in range(5): (1) print(f'第{i+1}次{name}打墙中')#windows下不能直接像下⾯这样引⽤,新建进程时会先import 进程.py原⽂件---执⾏--导⼊--执⾏--,陷⼊⽆限递归中报错。# ⼀定要在main下⾯使⽤,这样即使导⼊进程脚本,也会因为运⾏的不是原脚本⽂件⽽不再继续执⾏#linux/mac上不会报错,引⼊机制不同。# p1=Process(target=work2,args=('musen',))# ()# work1()def main(): t1 = Process(target = work2 , args = ('musen' ,)) # Thread(target=work2,kwargs={'name':'musen'}) 这种⽅式传参 () work1()

#单任务,多进程if __name__ == '__main__': main()创建进程类from multiprocessing import Processclass MyProcess(Process): def run(self): with open('','a',encoding = 'utf8') as f: for i in range(2): ('pythonn')def main(): p_list=[] for i in range(3): p=MyProcess() ()

for j in p_list: ()if __name__=="__main__": main()进程参数:p=s(group=None, target=None, name=None, args=(), kwargs={}, daemon=None)1. group 参数未使⽤,值始终为None,⼤部分情况⽤不到2. target 表⽰调⽤对象,即⼦进程要执⾏的任务3. args 表⽰调⽤对象的位置参数元组,args=(1,2,'egon',)4. kwargs 表⽰调⽤对象的字典,kwargs={'name':'egon','age':18}5. name 为⼦进程的名称Process创建的实例⽅法:1. ():启动进程,并调⽤该⼦进程中的()2. (): 进程启动时运⾏的⽅法,正是它去调⽤target指定的函数,我们⾃定义类的类中⼀定要实现该⽅法3. ate(): 强制终⽌⼦进程p,不会进⾏任何清理操作,如果p创建了⼦进程,该⼦进程就成了僵⼫进程,使⽤该⽅法需要特别⼩⼼这种情况。如果p还保存了⼀个锁那么也将不会被释放,进⽽导致死锁4. _alive(): 判断进程是否活着,如果p仍然运⾏,返回True5. ([timeout]): 是否等待⼦进程结束,(强调:是主进程处于等的状态,⽽p是处于运⾏的状态)。timeout是可选的超时时间,需要强调的是,只能join住start开启的进程,⽽不能join住run开启的进程Process创建的实例属性:1. :默认值为False,如果设为True,代表p为后台运⾏的守护进程,当p的⽗进程终⽌时,p也随之终⽌,并且设定为True后,p不能创建⾃⼰的新进程,必须在()之前设置2. :进程的名称,默认为Process-N,N为从1开始递增的整数3. :进程的pid,进程号,也可以通过()获取当前进程号4. de:进程在运⾏时为None、如果为–N,表⽰被信号N结束(了解即可)5. y:进程的⾝份验证键,默认是由m()随机⽣成的32字符的字符串。这个键的⽤途是为涉及⽹络连接的底层进程间通信提供安全性,这类连接只有在具有相同的⾝份验证键时才能成功(了解即可)多进程之间不共享全局变量import osfrom multiprocessing import Processnum=0def work1(): global num for i in range(100000): num+=1 print(F'进程号{()}',num)def work2(): global num for i in range(100000): num+=1 print(F'进程号{()}',num)def main(): p1=Process(target=work1) p2=Process(target=work2) () () () () print('主进程num值',num)if __name__=='__main__': main() #返回 进程号11844 100000, 进程号2224 100000,主进程num值 0多进程争夺共有资源读写操作时,会产⽣覆盖。为了避免这种情况,使进程串⾏处理。需要加锁from multiprocessing import Process,Lockdef work3(metux): e() with open('' , 'a' , encoding = 'utf8') as f : for i in range(3) : ('pythonn') e()

def work4(metux): e() with open('' , 'a' , encoding = 'utf8') as f : for i in range(3) : ('javan') e()def main(): metux=Lock() p1=Process(target=work3,args = (metux,)) p2=Process(target=work4,args = (metux,)) () () () ()if __name__=='__main__': main()

进程之间的通信:使⽤队列queue模块的队列:适⽤于同⼀进程中,各线程之间的通信multiprocessing进程模块的队列:适⽤于不同进程之间的通信。注意点:需要通过参数传⼊进程类中。import osfrom multiprocessing import Process,Queueq=Queue()for i in range(5): (i)

def work1(q): while not (): print('work1--------',(),())def work2(q): while not () : print('work2--------',(),())def main(): p1=Process(target=work1,args = (q,)) p2=Process(target=work2,args = (q,)) () ()

if __name__=='__main__': main()

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690957083a472688.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信