Python的进程和线程是使用的操作系统的原生线程和进程,其是去调用操作系统的相应接口实现

进程:之间不可直接共享数据,是资源的集合,进程必须有一个线程

线程:基于进程,之间可直接共享数据,可执行,只有所有的线程执行完毕程序才会退出

守护线程:生命值依赖于创建它的主线程,主程序亡,不管守护进程执行到何步也必须立即亡

多线程:不适用与CPU操作任务大的(如计算等),较适合于IO操作任务大的(如文件读写等)

简单的进程

Windows上启动进程必须加入【if __name__==“__main__”:】,而在linux上则可随意,进程的使用基本与线程相同

  1. import multiprocessing
  2. import time
  3. def run11():
  4. print("----- 进程 ----")
  5. # win 进程启动,必须加入这句
  6. if __name__=="__main__":
  7. #启动进程
  8. t1=multiprocessing.Process(target=run11,args=())
  9. t1.start()

进程间传递数据之进程队列:

  1. 1 import multiprocessing
  2. 2
  3. 3 def run11(qqlistx):
  4. 4 print("****** 进入进程 ********")
  5. 5 #设置进程数据
  6. 6 qqlistx.put("11111122")
  7. 7
  8. 8 # win 进程启动,必须加入这句
  9. 9 if __name__=="__main__":
  10. 10
  11. 11 #进程队列
  12. 12 qqlistx = multiprocessing.Queue()
  13. 13
  14. 14 #启动进程,必须传递进程队列
  15. 15 t1=multiprocessing.Process(target=run11,args=(qqlistx,))
  16. 16 t1.start()
  17. 17
  18. 18 print("得到进程数据:", qqlistx.get())

进程间传递数据之管道:

  1. 1 import multiprocessing
  2. 2
  3. 3 def run11(pp1):
  4. 4 print("****** 进入进程 ********")
  5. 5
  6. 6 #发送数据
  7. 7 pp1.send("东小东")
  8. 8 print("收到mian进程发来的数据:",pp1.recv())
  9. 9
  10. 10 # win 进程启动,必须加入这句
  11. 11 if __name__=="__main__":
  12. 12
  13. 13 #得到管道
  14. 14 # 得到两端,如同socket的服务器和客户端
  15. 15 #任意一端都可以进行收发
  16. 16 pp1,pp2 = multiprocessing.Pipe()
  17. 17
  18. 18 #启动进程,传递任意一端
  19. 19 t1=multiprocessing.Process(target=run11,args=(pp1,))
  20. 20 t1.start()
  21. 21
  22. 22 #另一端接收数据
  23. 23 print("得到进程数据:", pp2.recv())
  24. 24 pp2.send("收到数据了东小东")

进程之数据共享:

两个进程进行数据共享,列表或者字典数据共享

  1. 1 import multiprocessing
  2. 2
  3. 3 def run11(vv):
  4. 4 print("****** 进入进程 ********")
  5. 5
  6. 6 vv["dong"]="dongxiaodong"
  7. 7 #vv.append("555") #列表
  8. 8
  9. 9 # win 进程启动,必须加入这句
  10. 10 if __name__=="__main__":
  11. 11
  12. 12 #方法一 -------------:
  13. 13 # with multiprocessing.Manager() as mssaagex:
  14. 14 # dictx=mssaagex.dict() #得到字典参数
  15. 15 # #listx=mssaagex.list() #得到列表参数
  16. 16 #
  17. 17 # #启动进程,传递字典或者列表
  18. 18 # t1=multiprocessing.Process(target=run11,args=(dictx,))
  19. 19 # t1.start()
  20. 20 #
  21. 21 # #等待进程接收
  22. 22 # t1.join()
  23. 23 #
  24. 24 # #打印字典数据
  25. 25 # print("得到进程数据:", dictx)
  26. 26
  27. 27 #方法二 -------------------:
  28. 28 dictx=multiprocessing.Manager().dict() #得到字典参数
  29. 29 #listx=multiprocessing.Manager().list() #得到列表参数
  30. 30
  31. 31 #启动进程,传递字典或者列表
  32. 32 t2=multiprocessing.Process(target=run11,args=(dictx,))
  33. 33 t2.start()
  34. 34
  35. 35 #等待进程接收
  36. 36 t2.join()
  37. 37
  38. 38 #打印字典数据
  39. 39 print("得到进程数据:", dictx)

进程锁:

可以保护屏幕打印等,如多个进程同时向屏幕输出数据时,可以保证屏幕数据来自于一个进程,不会出现数据混乱问题

  1. 1 import multiprocessing
  2. 2
  3. 3 def run11(vv):
  4. 4 vv.acquire() #上锁
  5. 5 print("****** 进入进程 ********")
  6. 6 vv.release() #解锁
  7. 7
  8. 8
  9. 9 # win 进程启动,必须加入这句
  10. 10 if __name__=="__main__":
  11. 11
  12. 12 lockx=multiprocessing.Lock() #得到进程锁
  13. 13
  14. 14 t2=multiprocessing.Process(target=run11,args=(lockx,))
  15. 15 t2.start()

进程池:

确定进程的同时运行个数,更好的进行进程管理

  1. 1 import multiprocessing
  2. 2 import time
  3. 3
  4. 4 def run11(vv):
  5. 5 time.sleep(1)
  6. 6 print("****** 进入进程 ********",vv)
  7. 7
  8. 8 #回调函数
  9. 9 #在主进程中运行
  10. 10 def Cal(arg):
  11. 11 print("每个进程的回调函数",arg)
  12. 12
  13. 13 # win 进程启动,必须加入这句
  14. 14 if __name__=="__main__":
  15. 15
  16. 16 poolx=multiprocessing.Pool(2) #得到进程池,最多同时执行2个进程
  17. 17
  18. 18 #启动进程
  19. 19 for i in range(10):
  20. 20 #poolx.apply_async(func=run11,args=(i,)) #并行
  21. 21 poolx.apply_async(func=run11,args=(i,),callback=Cal) #并行并加入执行完毕的回调函数
  22. 22 #poolx.apply(func=run11,args=(i,)) #串行
  23. 23
  24. 24 #等待并关闭进程
  25. 25 poolx.close()
  26. 26 poolx.join()
  27. 27 print("----- 完毕 -----")

单线程实现高并发

安装:pip3 install gevent

手动切换:

  1. import greenlet
  2. def gfunx1():
  3. print("----gfunx1---")
  4. g2.switch() #手动切换到 gfunx2 中
  5.  
  6. def gfunx2():
  7. print("---gfunx2----")
  8. #声明两个协程
  9. g1=greenlet.greenlet(gfunx1)
  10. g2=greenlet.greenlet(gfunx2)
  11. g1.switch() #手动切换到 gfunx1 中

自动切换:

默认是先运行完gfunx1然后再运行gfunx2,但当遇到IO操作则会自动跳转到另一个协程工作,以此实现在协程中遇到IO就互相切换执行的效果

  1. 1 import gevent
  2. 2
  3. 3 def gfunx1():
  4. 4 print("---- gfunx1 ---")
  5. 5 gevent.sleep(3) #模拟 IO 操作为 3 秒,但使用time.sleep(x)则会进行阻塞
  6. 6 print("**** 三秒io操作结束 ******")
  7. 7
  8. 8 def gfunx2():
  9. 9 print("---- gfunx2 ----")
  10. 10
  11. 11
  12. 12 #开启两个协程
  13. 13 gevent.joinall([
  14. 14 gevent.spawn(gfunx1),
  15. 15 gevent.spawn(gfunx2),
  16. 16 ])
  1. 自动切换进阶:
  1. 将一系列阻塞操作让协程识别为IO操作

  1. 1 import gevent
  2. 2 from gevent import monkey
  3. 3 #将所有的阻塞操作(如:网络,延时,文件等)都视为gevent可捕获的IO阻塞操作
  4. 4 #根据库作者提示:此句最好放在其它库import之前,否则会出现警告
  5. 5 monkey.patch_all()
  6. 6
  7. 7 import requests
  8. 8 import time
  9. 9
  10. 10 def gfunx1():
  11. 11 print("---- gfunx1 ---")
  12. 12 res=requests.get("https://img2018.cnblogs.com/blog/1485202/201811/1485202-20181116215233782-319594948.png")
  13. 13 open("ww.jpg","wb").write(res.content) #以二进制写文件
  14. 14 print("**** 网络操作结束 ******")
  15. 15
  16. 16 def gfunx2():
  17. 17 print("---- gfunx2 ----")
  18. 18 time.sleep(3) #延时操作也已视为IO阻塞
  19. 19 print("*** 延时操作结束 3s ***")
  20. 20
  21. 21 def gfunx3(varx):
  22. 22 print("---- gfunx3 ----",varx)
  23. 23 time.sleep(1)
  24. 24 print("*** 延时操作结束 1s ***")
  25. 25
  26. 26
  27. 27 #开启三个协程
  28. 28 gevent.joinall([
  29. 29 gevent.spawn(gfunx1),
  30. 30 gevent.spawn(gfunx2),
  31. 31 gevent.spawn(gfunx3,"33333") #传递参数
  32. 32 ])

版权声明:本文为dongxiaodong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dongxiaodong/p/10495501.html