zoukankan      html  css  js  c++  java
  • 并发编程

    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 gevent
    gevent:封装了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()
  • 相关阅读:
    POJ 1887 Testing the CATCHER
    HDU 3374 String Problem
    HDU 2609 How many
    POJ 1509 Glass Beads
    POJ 1458 Common Subsequence
    POJ 1159 Palindrome
    POJ 1056 IMMEDIATE DECODABILITY
    POJ 3080 Blue Jeans
    POJ 1200 Crazy Search
    软件体系结构的艺术阅读笔记1
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/9401008.html
Copyright © 2011-2022 走看看