线程和协程

来源:互联网 发布:数据挖掘简答题 编辑:程序博客网 时间:2024/05/02 00:34

原链接:https://community.bwbot.org/topic/98

在写程序的时候为了提高执行效率经常会用到线程.把任务分配到不同的线程里面同时执行,这样即使其中一个被阻塞了,程序还是可以运行,程序运行效率得到了很大的提高.线程是一个经常用到的概念这里就不多说了.

但是随着大家使用的线程越来越多,线程的劣势就越来越明显了.最有名的就是c10k问题.c10k问题是在写服务器程序时遇到的.如何使一个服务器同时和10K个客户端保持网络连接?一般的做法是给每个连接开一个独立的线程,但是这样就会有上万个线程.大量的资源被浪费在线程的管理上.线程已经无法再胜任这个任务了.

在javascript中处理异步问题的方式给了我们很好的思路.javascript程序是单线程的,也就是某一时刻只能有一个程序在运行.但是javascript却可以很好的处理异步问题.下面以一个读取文件的例子来说明

var fs = require('fs'); //引入文件处理库 fsfs.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 ia = test() # a就是一个generatora.next() # 返回1a.next() # 返回2a.next() # 返回3# 直到10a.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 Truedef code1():    mDefer = Defer()    # start a new thread, and do some time consuming works    # when the work is complete    mDefer.resolve(results)    return mDeferdef code2():    mDefer = Defer()    # start a new thread, and do some time consuming works    # when the work is complete    mDefer.resolve(results)    return mDefereventList = []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 asyncioeventloop = 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语言自身的限制造成的.

原创粉丝点击