DDR爱好者之家 Design By 杰米
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()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米
暂无评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年11月26日
2024年11月26日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]