协程
迭代器内置iter方法---为了实现for循环,for循环的本质是调用可迭代对象的iter方法
迭代器也是可迭代对象
并发的本质--只是看起来是同时运行,其本质是 切+保存状态
协程--单线程实现并发。又称微线程,纤程。Coroutine。
用户从应用程序级别控制单线程下任务的切换,**一定是IO切**
一句话说明什么是线程---用户态的轻量级线程,即协程是由用户程序自己控制调度的
用户态(程序状态器指令字-0),内核态(程序状态器指令字-1)---自己去了解
优点--最大限度利用CPU
缺点--只能在单线程下,无法利用多核
特点:
必须在只有一个单线程里实现并发,
修改共享数据不需要加锁--没有同时运行的
用户程序里自己保存多个控制流的上下文栈
gevent模块--自动切换,检测IO
greenlet和yield一样都无法检测IO,然后自动切换,好处greenlet比yield切换方式更加方便
 
import time def producer(): res=[] for i in range(10000000): res.append(i) return res def consumer(res): pass start=time.time() res=producer() consumer(res) stop=time.time() print(stop-start) import time def producer(): g=consumer() next(g) for i in range(10000000): g.send(i) def consumer(): while True: n=yield start=time.time() producer() stop=time.time() print(stop-start) import time def producer(): g=consumer() next(g) for i in range(10000000): print('producer') time.sleep(10) g.send(i) def consumer(): while True: print('consumer') n=yield producer()
 
from greenlet import greenlet import time def eat(name): print("%s eat 1"%name) time.sleep(10) g2.switch("alex") print("%s eat 2"%name) g2.switch() def play(name): print("%s play 1"%name) g1.switch() print("%s play 2"%name) g1 = greenlet(eat) g2 = greenlet(play)
gevent模块
方法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的 g2=gevent.spawn(func2) g1.join() #等待g1结束 g2.join() #等待g2结束 gevent.sleep()#--模拟IO 或者上述两步合作一步:gevent.joinall([g1,g2]) g1.value#拿到func1的返回值
 
import gevent,time def eat(name): print("%s eat 1"%name) gevent.sleep(3) print("%s eat 2"%name) def play(name): print("%s play 1"%name) gevent.sleep(1) print("%s play 2"%name) start = time.time() g1 = gevent.spawn(eat,"alex") g2 = gevent.spawn(play,"alex") # g1.join() # g2.join() gevent.joinall([g1,g2]) #--等价上面两行 stop = time.time() print(stop-start)
 
import gevent,time,os def eat(): print("%s eat 1"%os.getpid()) gevent.sleep(3) print("%s eat 2"%os.getpid()) def play(): print("%s play 1"%os.getpid()) gevent.sleep(1) print("%s play 2"%os.getpid()) start = time.time() g1 = gevent.spawn(eat) g2 = gevent.spawn(play) # g1.join() # g2.join() gevent.joinall([g1,g2]) #--等价上面两行 stop = time.time() print(stop-start)
 
import gevent,time from threading import current_thread def eat(): print("%s eat 1"%current_thread().getName()) gevent.sleep(3) print("%s eat 2"%current_thread().getName()) def play(): print("%s play 1"%current_thread().getName()) gevent.sleep(1) print("%s play 2"%current_thread().getName()) start = time.time() g1 = gevent.spawn(eat) g2 = gevent.spawn(play) # g1.join() # g2.join() gevent.joinall([g1,g2]) #--等价上面两行 stop = time.time() print(stop-start)
 
from gevent import monkey;monkey.patch_all() import gevent,time from threading import current_thread def eat(): print("%s eat 1"%current_thread().getName()) time.sleep(3) print("%s eat 2"%current_thread().getName()) def play(): print("%s play 1"%current_thread().getName()) time.sleep(1) print("%s play 2"%current_thread().getName()) start = time.time() g1 = gevent.spawn(eat) g2 = gevent.spawn(play) gevent.joinall([g1,g2]) #--等价上面两行 stop = time.time() print(stop-start)
 
from gevent import monkey;monkey.patch_all() from threading import current_thread import gevent,requests def get(url): print("%s is getting %s"%(current_thread().getName(),url)) response = requests.get(url) if response.status_code == 200: print({"url":len(response.text)}) g1 = gevent.spawn(get,"http://www.baidu.com") g2 = gevent.spawn(get,"http://www.python.org") g3 = gevent.spawn(get,"http://www.JD.com") g1.join() g2.join() g3.join()
单线程实现并发套接字
 
from gevent import monkey;monkey.patch_all() # 必须必须写到脚本最开始 from socket import * import gevent def myserver(ip,port): s = socket(AF_INET,SOCK_STREAM) s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) s.bind((ip,port)) s.listen(5) while True: conn,addr = s.accept() print("%s:%s"%(addr[0],addr[1])) g1 = gevent.spawn(talk, conn, addr) def talk(conn,addr): while True: try: data = conn.recv(1024) print("%s : %s [%s]"%(addr[0],addr[1],data)) if not data:break conn.send(data.upper()) except ConnectionResetError: break conn.close() if __name__ == '__main__': myserver("127.0.0.1",8077)
 
# from socket import * # # client = socket(AF_INET,SOCK_STREAM) # client.connect(("127.0.0.1",8077)) # # while True: # msg = input(">>>") # if not msg:continue # client.send(msg.encode("utf-8")) # data = client.recv(1024) # print(data.decode("utf-8")) # from threading import Thread from socket import * def myclient(): c = socket(AF_INET, SOCK_STREAM) c.connect(("127.0.0.1", 8077)) while True: c.send("hello".encode("utf-8")) print("send") data = c.recv(1024) print(data.decode("utf-8")) if __name__ == '__main__': for i in range(10): t = Thread(target=myclient) t.start()
******并发的方式 --- 多进程,多线程,单线程开协程
 
                    
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号