协程

  1. 协程的作用就是在执行某个子程序(函数)时,可以指定或者随机地中断,然后去执行其他的子程序(函数),在合适的时候再返回到中断子程序停止时的状态继续执行。听起像生成器的特性,实际上协程也是基于生成器的(但是无法做到检测IO切换)。所以协程是通过程序自身的控制,去切换不同任务,实现并发的效果。也就是协程是单线程执行,没有多线程由CPU调度时线程切换的开销,所以效率较高。
  1. from gevent import monkey;monkey.patch_all() # 固定编写 用于检测所有的IO操作
  2. from gevent import spawn
  3. import time
  4. def play(name):
  5. print('%s play 1' % name)
  6. time.sleep(1)
  7. print('%s play 2' % name)
  8. def eat(name):
  9. print('%s eat 1' % name)
  10. time.sleep(1)
  11. print('%s eat 2' % name)
  12. start_time = time.time()
  13. g1 = spawn(play, 'kevin')
  14. g2 = spawn(eat, 'kevin')
  15. g1.join() # 等待检测任务执行完毕
  16. g2.join() # 等待检测任务执行完毕
  17. print('总耗时:', time.time() - start_time) # 正常串行肯定是2S+
  18. # 总耗时: 1.001084804534912 代码控制切换

基于协程实现TCP服务端并发

服务端

  1. from gevent import monkey;monkey.patch_all() # 固定编写 用于检测所有的IO操作
  2. from gevent import spawn
  3. import socket
  4. def talk(sock):
  5. while True:
  6. data = sock.recv(1024) # IO操作
  7. print(data.encoude('utf8'))
  8. sock.send(data.upper())
  9. def get_server():
  10. IP = '127.0.0.1'
  11. PORT = 8080
  12. server = socket.socket()
  13. server.bind((IP, PORT))
  14. server.listen(5)
  15. while True:
  16. sock, addr = server.accept()
  17. spawn(talk, sock)
  18. g = spawn(get_server)
  19. g.join()

客户端

  1. import socket
  2. IP = '127.0.0.1'
  3. PORT = 8080
  4. client = socket.socket()
  5. client.connect((IP, PORT))
  6. client.send('hellow world'.encode('utf8'))
  7. data = client.recv(1024)
  8. print(data.decode('utf8'))

结论

python可以通过开设多进程 在多进程下开设多线程 在多线程使用协程,从而让程序执行的效率达到极致。但是,因为大部分程序都是IO密集型的,实际业务中很少需要如此之高的效率(一直占着CPU不放),了解即可