ROS Group 产品服务
Product Service 开源代码库
Github 官网
Official website 技术交流
Technological exchanges 激光雷达
LIDAR ROS教程
ROS Tourials 深度学习
Deep Learning 机器视觉
Computer Vision
线程和协程
-
在写程序的时候为了提高执行效率经常会用到线程.把任务分配到不同的线程里面同时执行,这样即使其中一个被阻塞了,程序还是可以运行,程序运行效率得到了很大的提高.线程是一个经常用到的概念这里就不多说了.
但是随着大家使用的线程越来越多,线程的劣势就越来越明显了.最有名的就是c10k问题.c10k问题是在写服务器程序时遇到的.如何使一个服务器同时和10K个客户端保持网络连接?一般的做法是给每个连接开一个独立的线程,但是这样就会有上万个线程.大量的资源被浪费在线程的管理上.线程已经无法再胜任这个任务了.
在javascript中处理异步问题的方式给了我们很好的思路.javascript程序是单线程的,也就是某一时刻只能有一个程序在运行.但是javascript却可以很好的处理异步问题.下面以一个读取文件的例子来说明
var fs = require('fs'); //引入文件处理库 fs fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); console.log("I'm not blocking");
readFile函数的第一个参数是文件路径, 第二个参数是回调函数.当文件读取完成或者失败的时候回调函数会被执行.
这样当程序运行到readFile的时候就不会被阻塞.也就是说在文件读取完成之前就会在终端中显示出I'm not blocking
这是怎么实现的呢?
这是因为javascript有一个叫做Event loop的线程,专门用来监控事件有没有触发,如果触发就调用相应的回调函数.比如说上面的readFile函数,实际上是相当于在Event Loop里面注册了一下.这就是协程的概念.用一个主线程去完成各种异步操作.看起来好像各自都有自己独立的线程一样.
具体怎么实现一个协程呢?我们可以用python从头开始搭建出来.
在python中有一种叫做generator的东西.比如
a = xrange(0,100000)
这里a就是一个generator.一般使用时会觉得a是一个list.但是不是这样的.a中的元素只有在被使用到的时候才会被生成.def test(): for i in range(0,10): yield i a = test() # a就是一个generator a.next() # 返回1 a.next() # 返回2 a.next() # 返回3 # 直到10 a.next() # 抛出 StopIteration 异常
这样a就可以用来表现协程的状态.在Event Loop之中不停的执行协程返回的generator直到这个generator返回StopIteration为止,再执行对应的回调函数.
class Defer: def __init__(self): self.waitFlag = True self.results = None def resolve(self, results): self.results = results self.waitFlag = False def get_status(self): while self.waitFlag: yield True def code1(): mDefer = Defer() # start a new thread, and do some time consuming works # when the work is complete mDefer.resolve(results) return mDefer def code2(): mDefer = Defer() # start a new thread, and do some time consuming works # when the work is complete mDefer.resolve(results) return mDefer eventList = [] eventList.append(code1()) eventList.append(code2()) while True: for event in eventList: try: event.get_status() except: results = event.results
个人感觉原理上就是如此了.
实际上python中协程的用法
为了方便使用,python把协程相关的东西做成了asyncio库.并且在python 3.5之中增加了await, async关键字(和C#学的)
一个用协程的Hello World例子
import asyncio eventloop = asyncio.new_event_loop() asyncio.set_event_loop(eventloop) async def helloWorld(): await asyncio.sleep(10) print("Hello World") eventloop.run_until_complete(helloWorld()) # 这一句是阻塞的,要等待目标任务完成才会执行下面的程序 print("I'm blocking")
更详细的关于python的协程信息可以看这里
不过个人感觉python的协程还是不是很自然.没有C#做的好.这个应该是python语言自身的限制造成的.