温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

python中Event事件、进程池、线程池以及协程的实例介绍

发布时间:2021-09-04 16:47:24 来源:亿速云 阅读:285 作者:chen 栏目:开发技术

这篇文章主要介绍“python中Event事件、进程池、线程池以及协程的实例介绍”,在日常操作中,相信很多人在python中Event事件、进程池、线程池以及协程的实例介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python中Event事件、进程池、线程池以及协程的实例介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Event事件

用来控制线程的执行

出现e.wait(),就会把这个线程设置为False,就不能执行这个任务;

只要有一个线程出现e.set(),就会告诉Event对象,把有e.wait的用户全部改为True,剩余的任务就会立马去执行。由一些线程去控制另一些线程,中间通过Event。

from threading import Event from threading import Thread import time # 调用Event实例化出对象 e = Event() # # # 若该方法出现在任务中,则为False,阻塞 # e.wait() # False # # 若该方法出现在任务中,则将其他线程的False改为True,进入就绪态和运行态 # e.set() # True def light():  print('红灯亮...')  time.sleep(5)  # 应该发出信号,告诉其他线程准备执行  e.set() # 将car中的False变为True  print('绿灯亮...') def car(name):  print('正在等红灯...')  # 让所有汽车任务进入阻塞态  e.wait() # False  print(f'{name}正在加速飘逸...') # 让一个light线程控制多个car线程 t = Thread(target=light) t.start() for i in range(10):  t = Thread(target=car, args=(f'汽车{i}号', ))  t.start()

进程池与线程池

进程池与线程池是用来控制当前程序允许创建(进程/线程)的数量

作用:保证在硬件允许的范围内创建(进程/线程)的数量

线程池使用一:

from concurrent.futures import ThreadPoolExecutor import time pool = ThreadPoolExecutor(5) # 5代表只能开启5个进程, 不加默认使用cpu的进程数 # ThreadPoolExecutor(5) # 5代表只能开启5个线程 # pool.submit() #异步提交任务, 括号里传函数地址 def task():  print('线程任务开始了...')  time.sleep(1)  print('线程任务结束了...') for line in range(5):  pool.submit(task)

使用二:

from concurrent.futures import ThreadPoolExecutor import time pool = ThreadPoolExecutor(5) # 5代表只能开启5个进程, 不加默认使用cpu的进程数 # ThreadPoolExecutor(5) # 5代表只能开启5个线程 # pool.submit() #异步提交任务, 括号里传函数地址 def task():  print('线程任务开始了...')  time.sleep(1)  print('线程任务结束了...')  return 123 # 回调函数 def call_back(res):  print(type(res))  res2 = res.result() # 注意:赋值操作不要与接收的res同名  print(res2) for line in range(5):  pool.submit(task).add_done_callback(call_back)

pool.shutdown() 会让所有线程池的任务结束后,才往下执行代码

多线程爬取梨视频

利用requests模块,封装底层socket套接字

  • 主页中获取所有视频id号,拼接视频详情页url

  • 在视频详情页中获取真实视频url srcUrl=

  • 往真实视频url地址发送请求获取 视频 二进制数据

  • 最后把视频二进制数据保存到本地

协程

  • 进程: 资源单位

  • 线程: 执行单位

  • 协程: 在单线程下实现并发

注意: 协程不是操作系统资源,目的是让单线程实现并发

协程目的

  • 操作系统:使用多道技术,切换 + 保存状态,一个是遇到IO, 另一个是CPU执行时间过长

  • 协程:通过手动模拟操作系统 “多道计数”, 实现 切换 + 保存状态

    • 手动实现,遇到IO切换,欺骗操作系统误以为没有IO操作

    • 单线程时,遇到IO,就切换 + 保存状态

    • 单线程时,对于计算密集型,来回切换 + 保存状态反而效率更低

优点:在IO密集型的情况下,会提高效率

缺点:若在计算密集型的情况下,来回切换,反而效率更低

import time def func1():  for i in range(10000000):   i+1 def func2():  for i in range(10000000):   i+1 start = time.time() func1() func2() stop = time.time() print(stop - start) # 1.0312113761901855 # 基于yield实现并发 在计算密集型的情况下效率更低 def func1():  while True:   10000000+1   yield def func2():  g = func1()  for i in range(10000000):   i+1   next(g) # 每次执行next相当于切换到func1下面 start = time.time() func2() stop = time.time() print(stop - start) # 1.3294126987457275

gevent

gevent是一个第三方模块,可以帮你监听IO操作,并切换

使用gevent的目的:在单线程下实现,遇到IO就会 保存状态 + 切换

import time from gevent import monkey monkey.patch_all() # 可以监听该程序下所有的IO操作 from gevent import spawn, joinall # 用于做切换 + 保存状态 def func1():  print('1')  time.sleep(1) # IO操作 def func2():  print('2')  time.sleep(3) def func3():  print('3')  time.sleep(5) start = time.time() s1 = spawn(func1) s2 = spawn(func2) s3 = spawn(func3) s1.join() # 发送信号,相当于等待自己(在单线程的情况下) s2.join() s3.join() # joinall((s1, s2, s3)) # 一个个执行很麻烦,可以用joinall把这些全部装进去 end = time.time() print(end - start) # 5.006161451339722

TCP服务端socket套接字实现协程

服务端:

from gevent import monkey from gevent import spawn import socket monkey.patch_all() server = socket.socket() server.bind(('127.0.0.1', 9999)) server.listen(5) def task(conn):  while True:   try:    data = conn.recv(1024)    if len(data) == 0:     break    print(data.decode('utf-8'))    send_data = data.upper()    conn.send(send_data)   except Exception:    break  conn.close() def server2():  while True:   conn, addr = server.accept()   print(addr)   spawn(task, conn) if __name__ == '__main__':  s = spawn(server2)  s.join()

客户端:

import socket from threading import Thread, current_thread def client():  client = socket.socket()  client.connect(('127.0.0.1', 9999))  number = 0  while True:   send_data = f'{current_thread().name} {number}'   client.send(send_data.encode('utf-8'))   data = client.recv(1024)   print(data.decode('utf-8'))   number += 1 for i in range(400):  t = Thread(target=client)  t.start()

到此,关于“python中Event事件、进程池、线程池以及协程的实例介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI