进程_线程 之(六) --- 协程

协程简介

区别:线程和进程的操作是由程序触发系统接口,执行者是系统;协程的操作则是程序员。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

协成的原理:利用一个线程,分解一个线程成为多个微线程,注意此时从程序级别来分解的

适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;

实现技术

需要手动安装 greenlet模块 和 gevent模块。安装gevent模块会默认安装greenlet模块

基于底层greenlet实现

 1 from greenlet import greenlet
 2
 3 def test1():
 4     print(1,2)      # 2.执行输出语句,输出1,2
 5     gr2.switch()    # 3.执行完上面输出语句后,此行调用test2函数
 6     print(3,4)        # 6.执行输出语句,输出3,4
 7     gr2.switch()     # 7.执行完上面输出语句后,此处调用test2函数
 8
 9 def test2():
10     print(5,6)     # 4.执行输出语句,输出5,6
11     gr1.switch()     # 5.执行完上面输出语句后,此行调用test1函数
12     print(7,8)     # 8.执行输出语句,输出7,8
13
14 gr1 = greenlet(test1) # 1.调用grl1对应的test1函数
15 gr2 = greenlet(test2)
16 gr1.switch()

1 1,2
2 5,6
3 3,4
4 7,8

输出结果

基于底层gevent实现

 1 import gevent
 2
 3 def foo():
 4     print(‘Running in foo‘)
 5     gevent.sleep(0)
 6     print(‘Explicit context switch to foo again‘)
 7
 8 def bar():
 9     print(‘Explicit context to bar‘)
10     gevent.sleep(0)
11     print(‘Implicit context switch back to bar‘)
12
13 gevent.joinall([
14     gevent.spawn(foo),
15     gevent.spawn(bar),
16 ])

1 Running in foo
2 Explicit context to bar
3 Explicit context switch to foo again
4 Implicit context switch back to bar

输出结果

实例

 1 from gevent import monkey; monkey.patch_all()
 2 import gevent
 3 import requests
 4
 5 def f(url):
 6     print(‘GET: %s‘ % url)
 7     resp = requests.get(url)
 8     data = resp.text
 9     print(‘%d bytes received from %s.‘ % (len(data), url))
10
11 gevent.joinall([
12         gevent.spawn(f, ‘https://www.python.org/‘),
13         gevent.spawn(f, ‘https://www.yahoo.com/‘),
14         gevent.spawn(f, ‘https://github.com/‘),
15 ])

1 GET: https://www.python.org/
2 GET: https://www.yahoo.com/
3 GET: https://github.com/
4 431218 bytes received from https://www.yahoo.com/.
5 25529 bytes received from https://github.com/.
6 47394 bytes received from https://www.python.org/.

输出结果

原文地址:https://www.cnblogs.com/TMMM/p/10786226.html

时间: 2024-10-28 22:21:40

进程_线程 之(六) --- 协程的相关文章

区分python进程、线程、携协程

进程: 概念:对各种资源管理的集合.(线程也是一种资源) 使用场景:CPU密集型运算,调用多进程,通过socket传输数据 线程: 概念:CPU运算的最小单元 使用场景:没有明确的切换条件,只能通过定时器切换 注:python中只允许单线程操作内存中数据,也就是说用python即使开了多个线程实际上也是切换执行,并没有利用CPU的多核性能.究其原因,是python的全局解释器锁(GIL).个人觉得,设计GIL与python的出发点相符,让程序更加简单,节省程序员时间,所以应用粗粒度的线程锁可以免

进程池与线程池、协程、协程实现TCP服务端并发、IO模型

进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度的利用计算机 什么是池? 在保证计算机硬件安全的情况下最大限度的利用计算机 池其实是降低了程序的运行效率,但是保证了计算机硬件的安全 (硬件的发展跟不上软件的速度) ''' from concurrent.futures import ThreadPoolExecutor import time p

异步回调,事件,线程池与协程

在发起一个异步任务时,指定一个函数任务完成后调用函数 为什么需要异步 在使用线程池或进程池提交任务时想要任务的结果然后将结果处理,调用shudown 或者result会阻塞 影响效率,这样的话采用异步调用 比如result本来是用水壶烧水烧开了拿走,烧下一个 用shutdown可以将水壶一起烧但是一个一个拿走 call_done_back是一起烧,每个好了会叫你拿走做其他事 . 1.使用进程池时,回调函数都是主进程中执行执行 2. 使用线程池时,回调函数的执行线程是不确定的,哪个线程空闲就交给哪

异步调用,线程队列,时间,协程

异步的使用场景 爬虫: 1.从目标站点下载网页数据,本质是HTML格式字符串 2.用re从字符串中提取出你所需要的数据 #使用进程池 from concurrent.futures import ProcessPoolExecutor import requests,re,os def get_data(url): print('%s正在请求%s'%(os.getpid(),url)) response = requests.get(url) #获取网页数据包含报头 print('%s请求%s成

线程进阶之线程队列、线程池和协程

本节目录: 1.线程队列 2.线程池 3.协程 一.线程队列 线程之间的通信我们列表行不行呢,当然行,那么队列和列表有什么区别呢? queue队列 :使用import queue,用法与进程Queue一样 queue is especially useful in threaded programming when information must be exchanged safely between multiple threads. class queue.Queue(maxsize=0)

python 38 线程队列与协程

目录 1. 线程队列 1.1 先进先出(FIFO) 1.2 后进先出(LIFO)堆栈 1.3 优先级队列 2. 事件event 3. 协程 4. Greenlet 模块 5. Gevent模块 1. 线程队列 1.1 先进先出(FIFO) import queue q = queue.Queue(3) q.put('a') q.put('b') q.put('c') print(q.qsize()) # 队列大小 print(q.get()) print(q.get()) print(q.get

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

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

Python 37 进程池与线程池 、 协程

一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后,不是原地等待,而是直接执行下一行代码,会导致任务是并发执行的,结果future对象会在任务运行完毕后自动传给回调函数 二:协程 基于单线程下实现并发,只有一个主线程(如下图:可利用的CPU只有一个)的情况下实现并发,并发的本质:切换+保存状态 CPU正在运行一个任务,会在两种情况下自习其他任务(切换

GIL线程全局锁 协程

GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务,python的多线程起到作用,但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢. 见Python 最难的问题 解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能). 19 协程 知乎被问到了,呵呵哒,跪了 简单点说协程是进程和线