寫在前面
- 上一篇文章[Python3簡單實作多任務(多程序篇)]已經介紹了python多程序實作多任務的簡單實作方法;
- 這次講一講python建立多任務另外兩種常見的方式:
協程和線程
線程多任務實作1:直接使用Thread建立線程
from threading import Thread
import threading
import os
import time
import random
def 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 Thread
import threading
import os
import random
import time
class 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 time
import random
import gevent
from 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 time
def 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 time
from greenlet import greenlet
activate = None
sleep = None
def 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()
小結
- 線程與程序相比,占用資源更少,但線程依賴于程序,一個程序可以有多個線程,程序完成任務依賴于内部的線程;
- 協程解決了線程之間争用資源引發的資源浪費,是以協程比線程占用的資源更少.