写在前面
上一篇文章[Python3简单实现多任务(多进程篇)]已经介绍了python多进程实现多任务的简单实现方法;
这次讲一讲python创建多任务另外两种常见的方式:
协程和线程
线程多任务实现1:直接使用Thread创建线程
from threading import Threadimport threadingimport osimport timeimport randomdef not_know(thread_num): print("第%d线程吟唱:不知天上宫阙"%(thread_num)) time.sleep(random.random()) print("第%d线程吟唱:今夕是何年"%(thread_num)) time.sleep(random.random()) print("第%d号线程:<吟唱古诗>任务结束..."%(thread_num))def main(): for i in range(1, 6): num = len(threading.enumerate()) print("当前线程数为:%d"%num) t = Thread(target=not_know, args=(i,)) t.start() time.sleep(0.8)if __name__ == "__main__": print("--->主函数开始运行<---") main() print("--->主函数运行完毕<---")
线程多任务实现2:定义类继承threading.Thread,然后重写run方法(run方法相当于功能函数)
from threading import Threadimport threadingimport osimport randomimport timeclass the_cosmetic(threading.Thread): def __init__(self, num): self.num = num # 一定要记得调用父类构造方法 threading.Thread.__init__(self) def run(self): print("-->第%d线程开始执行<--"%self.num) time.sleep(random.random()) print("%d最有效的化妆品是什么?"%self.num) time.sleep(random.random()) print("%dPhotoshop是最好的化妆品!"%self.num) time.sleep(random.random()) print("-->第%d线程执行完毕<--"%self.num)def main(): print("-------->开始创建线程<--------") for i in range(1, 6): t = the_cosmetic(i) t.start() print("-------->线程创建完毕<--------")if __name__ == "__main__": main()
协程多任务实现1:gevent(使用简单,推荐!需要pip安装gevent)
sudo pip3 install gevent
import timeimport randomimport geventfrom gevent import monkey monkey.patch_all()def peach(name): for i in range(1, 6): start_time = time.time() time.sleep(random.random()) end_time = time.time() # 使用 round() 控制小数点位数! print("%s产出第%s个桃子,耗时%s"%(name, i, round(end_time - start_time, 2)))def apple(name): for i in range(1, 8): start_time = time.time() time.sleep(random.random()) end_time = time.time() print("%s产出第%s个苹果,耗时%s"%(name, i, round(end_time - start_time, 2)))def main(): # 注意:下面的语句,没有等号! 没有等号! 没有等号! gevent.joinall([ gevent.spawn(peach,"LI"), gevent.spawn(apple,"HO"), ])if __name__ == "__main__": main()
协程多任务实现2:yield实现协程(yield最底层,最灵活,是python自带的模块)
import timedef to_activate(): yield print("吃早饭") print("读文档") yield print("吃中午饭") print("写程序") yield print("吃晚饭") print("解bug")def to_sleep(): yield print("午睡") yield print("晚休")def main(): print("程序员的一天") activate = to_activate() sleep = to_sleep() # 利用yield开始在两个函数间跳转 next(activate) next(sleep) next(activate) next(sleep) next(activate) print("程序员的一天结束了")if __name__ == "__main__": main()
协程多任务实现3:greenlet实现协程(模块须通过pip单独安装,个人感觉这个模块封装的并不够好,所以放到最后,仅供了解)
sudo pip3 install greenlet
import timefrom greenlet import greenlet activate = Nonesleep = Nonedef to_activate(): print("吃早饭") print("读文档") sleep.switch() print("吃中午饭") print("写程序") print("吃晚饭") print("解bug")def to_sleep(): print("午睡") activate.switch() print("晚休")def main(): global activate global sleep print("程序员的一天") activate = greenlet(to_activate) sleep = greenlet(to_sleep) #从activate开始执行 activate.switch() print("程序员的一天结束了")if __name__ == "__main__": main()
小结
线程与进程相比,占用资源更少,但线程依赖于进程,一个进程可以有多个线程,进程完成任务依赖于内部的线程;
协程解决了线程之间争用资源引发的资源浪费,所以协程比线程占用的资源更少.