并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信

1.协程并发:切+保存状态单线程下实现并发:协程  切+ 保存状态  yield    遇到io切,提高效率    遇到计算切,并没有提高效率

检测单线程下 IO行为 io阻塞 切     相当于骗操作系统 一直处于计算协程:。。。单线程下实现并发:根本目标:遇到IO就切,一个线程的整体IO降下来程序用的cpu 时间长,就叫执行效率高效率最高:多个进程  (多个cpu)          每个进程开多个线程          每个线程用到协程 (IO就切)总结协程特点:
 1 #并发执行
 2 import time
 3
 4 def producer():
 5     g=consumer()
 6     next(g)
 7     for i in range(10000000):  # 计算
 8         g.send(i)
 9
10
11 def consumer():
12     while True:
13         res=yield
14
15
16 start_time=time.time()
17 producer()
18 stop_time=time.time()
19 print(stop_time-start_time)
20
21 #串行
22 import time
23
24 def producer():
25     res=[]
26     for i in range(10000000):
27         res.append(i)
28     return res
29
30
31 def consumer(res):
32     pass
33
34
35 start_time=time.time()
36 res=producer()
37 consumer(res)
38 stop_time=time.time()
39 print(stop_time-start_time)
2.greenlet模块pip3 install greenlet greenlet:可以很方便的切 但不能检测到 遇到IO 切 greenlet 比yield 好 但是还是不好 遇到io不会切
 1 from greenlet import greenlet
 2 import time
 3
 4 def eat(name):
 5     print(‘%s eat 1‘ %name)
 6     time.sleep(10)  # 遇到io 不会立即切
 7     g2.switch(‘egon‘)
 8     print(‘%s eat 2‘ %name)
 9     g2.switch()
10
11 def play(name):
12     print(‘%s play 1‘ %name )
13     g1.switch()
14     print(‘%s play 2‘ %name )
15
16
17 g1=greenlet(eat)
18 g2=greenlet(play)
19
20 g1.switch(‘egon‘) # 第一次切 需要传参数
3.gevent模块pip3 install geventgevent:封装了greenlet模块,但是他能检测到io 自动切    只能检测到gevent.sleep() gevent的IO阻塞    加上补丁后,就可以检测到所有的IO 原理是:将阻塞变为非阻塞    from gevent import monkey;monkey.patch_all()这种形式的协程 才能帮我们提升效率 从始至终 就一个线程gevent.joinall([g1,g2])   等待全部执行完

gevent 模块:监测单线程下多个任务得IO行为实现遇到IO就自动切到另一个任务去执行     提升单线程运行效率     应用场景:单线程下多个任务io密集型ftp io密集型 线程来回切 比os q切 小路高
 1 from gevent import monkey;monkey.patch_all()  # 一定要放在程序的开头 检测所以的io 将阻塞变成非阻塞
 2 import gevent
 3 import time
 4
 5
 6 def eat(name):
 7     print(‘%s eat 1‘ % name)
 8     time.sleep(3)  # 7s多一些 gevent 只识别 gevent 的 io操作
 9     # gevent.sleep(3)  # 4s 多一些
10     print(‘%s eat 2‘ % name)
11
12
13 def play(name):
14     print(‘%s play 1‘ % name)
15     time.sleep(4)
16     # gevent.sleep(4)
17     print(‘%s play 2‘ % name)
18
19
20 start_time=time.time()
21 g1=gevent.spawn(eat,‘egon‘)
22 g2=gevent.spawn(play,‘alex‘)
23
24 g1.join()
25 g2.join()
26 stop_time=time.time()
27 print(stop_time-start_time)
28 """
29 egon eat 1
30 alex play 1
31 egon eat 2
32 alex play 2
33 4.001747369766235
34
35 """
36 """
37 egon eat 1
38 egon eat 2
39 alex play 1
40 alex play 2
41 7.0017828941345215
42 """
43 """
44 egon eat 1
45 alex play 1
46 egon eat 2
47 alex play 2
48 4.001675367355347
49 """
50
51 from gevent import monkey;monkey.patch_all()
52 import gevent
53 import time
54
55
56 def eat(name):
57     print(‘%s eat 1‘ % name)
58     time.sleep(3)
59     print(‘%s eat 2‘ % name)
60
61
62 def play(name):
63     print(‘%s play 1‘ % name)
64     time.sleep(4)
65     print(‘%s play 2‘ % name)
66
67
68 g1=gevent.spawn(eat,‘egon‘)  # 异步操作
69 g2=gevent.spawn(play,‘alex‘)
70
71 # time.sleep(5)  # 得等到 全部执行完
72
73 # g1.join()  # 等到 全部执行完
74 # g2.join()
75
76 gevent.joinall([g1,g2])  # 等到g1 g2 全部执行完
77 """
78 egon eat 1
79 alex play 1
80 egon eat 2
81 alex play 2
82 """
4.gevent实现并发的套接字通信# 500 客户端同时 登录  服务端:这里1个线程 抗住了 500个client # 这里也说明了:单线程下面io问题降下来,效率大幅度提高

说明      使用:多进程            多线程            一个线程io 问题解决了 效率大大得提高服务端:
 1 #基于gevent实现
 2 from gevent import monkey,spawn;monkey.patch_all()
 3 from socket import *
 4
 5 def communicate(conn):
 6     while True:
 7         try:
 8             data=conn.recv(1024)
 9             if not data:break
10             conn.send(data.upper())
11         except ConnectionResetError:
12             break
13
14     conn.close()
15
16 def server(ip,port):
17     server = socket(AF_INET, SOCK_STREAM)
18     server.bind((ip,port))
19     server.listen(5)
20
21     while True:
22         conn, addr = server.accept()
23         spawn(communicate,conn)  # 这里没必要加join
24
25     server.close()
26
27 if __name__ == ‘__main__‘:
28     g=spawn(server,‘127.0.0.1‘,8090)
29     g.join()
客户端:
 1 from socket import *
 2 from threading import Thread,currentThread
 3
 4 def client():  #
 5     client=socket(AF_INET,SOCK_STREAM)
 6     client.connect((‘127.0.0.1‘,8090))
 7
 8
 9     while True:
10         client.send((‘%s hello‘ %currentThread().getName()).encode(‘utf-8‘))
11         data=client.recv(1024)
12         print(data.decode(‘utf-8‘))
13
14     client.close()
15
16  # 500 客户端同时 登录  服务端:这里1个线程 抗住了 500个client
17  # 这里也说明了:单线程下面io问题降下来,效率大幅度提高
18 if __name__ == ‘__main__‘:
19     for i in range(500):  # 500 客户端同时 登录  服务端:这里1个线程 抗住了 500个client
20         t=Thread(target=client)
21         t.start()

原文地址:https://www.cnblogs.com/alice-bj/p/8719143.html

时间: 2024-08-03 12:51:05

并发编程 - 协程 - 1.协程概念/2.greenlet模块/3.gevent模块/4.gevent实现并发的套接字通信的相关文章

python 并发编程 基于gevent模块 协程池 实现并发的套接字通信

基于协程池 实现并发的套接字通信 客户端: from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8080)) while True: msg = input(">>>:").strip() if not msg:break client.send(msg.encode("utf-8")) data = client.recv(

python全栈脱产第37天------进程池与线程池、协程、gevent模块、单线程下实现并发的套接字通信

一.进程池与线程池 调用concurrent.futures下的ThreadPoolExecutor,ProcessPoolExecutor来实现 提交任务有两种方式:同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,在执行下一段代码,是串行的 异步调用:提交完一个任务之后,不在原地等待,直接运行下一段代码,任务是并发的 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutorimp

27 Apr 18 GIL 多进程多线程使用场景 线程互斥锁与GIL对比 基于多线程实现并发的套接字通信 进程池与线程池 同步、异步、阻塞、非阻塞

27 Apr 18 一.全局解释器锁 (GIL) 运行test.py的流程: a.将python解释器的代码从硬盘读入内存 b.将test.py的代码从硬盘读入内存  (一个进程内装有两份代码) c.将test.py中的代码像字符串一样读入python解释器中解析执行 1 .GIL:全局解释器锁 (CPython解释器的特性) In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple na

并发编程中的几个名词概念

现在,高并发,高流量已成为行业的热点,并且各种高并发的技术也是层出不穷,如论是官方文档还是市面上的各种书籍,我们在阅读的时候都会遇到一些专业名词,理解这些专业名词之后,才能更好的理解内容. 一.同步与异步 介绍: 同步和异步通常来形容一次方法调用. 解释一:同步方法调用一旦开始,调用者必须等到方法的调用返回后,才能继续后续的行为.异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者可以继续后续的操作. 解释二:同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信

Java并发编程系列(一)基础概念

1.线程状态图: 5种状态: 1.新建(new) 2.就绪(Runnable) 3.运行(Running) 4.阻塞(Blocked) 等待阻塞:调用了wait()方法 同步阻塞:调用了synchronized()方法或执行了synchronized代码块,但是没有获取到对象的同步锁. 其他阻塞:调用sleep()或join()方法 5.死亡(Dead) 相关方法: 1.run(): 是Runnable接口里唯一的一个抽象方法,可以被重复调用.直接调用run方法,并不会启动新线程,程序中依然只有

高并发编程学习(一)——基本概念

一.几个重要的概念 1.同步(Synchronous)和异步(Asynchronous) 同步和异步通常用来形容一次方法调用. 同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为. 异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作.而异步方法通常会在另外一个线程中“真实”地执行. 同步和异步方法调用 2.并发(Concurrency)和并行(Parallelism) 并发和并行是两个非常容易被混淆的概念.它们都可以表示两个或者多个任务一

网络编程-socket实现简单套接字通信

Service import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#给予网络,机于TCP协议的通信 #端口0-65535 #0-1024给操作系统使用 phone.bind(('127.0.0.1',8080)) #开始监听,表最大挂起链接数 phone.listen(5) #等待链接 #res=phone.accept() #res是一个套接字对象和客户地址 conn,client_addr=phone.ac

网络编程基础【林老师版】:简单的 套接字通信(一)

一.服务端代码 import socket #1.买手机 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # print(phone) #2.绑定手机卡 phone.bind(('127.0.0.1',8081)) #0-65535:0-1024给操作系统使用 #3.开机 phone.listen(5) #4.等电话链接 print('starting...') conn,client_addr=phone.accept() #5.收

网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

TCP协议:三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立连接的请求 3:客户端接收到服务端发来的请求,返回接成功给服务端,完成双向连接 第一客戶向服务端发送请求,请求建立连接 服务端同客户端的请求,并同时向客户端发送建立 连接的请求,最后客户端同意后建立 双向连接. C ----> S C <---- S - 反馈机制: 客户端往服务端发送请求,服务端必须返回响应, 告诉客户