python多线程理解
在發送網絡請求的過程中,單個請求的速度總是有著很大的限制,而任務往往需要以更快的速度去執行,這時多線程就是一個很好地選擇。python已經給我們封裝好了多線程庫thread和threading。
thread:比較底層的模塊
threading:Higher-level threading interface
ps:建議使用threading模塊
- 高級別的threading模塊更為先進,對線程的支持更為完善
- 低級別的thread模塊同步原語很少
- thread模塊對線程什么時候結束完全沒有控制,當主線程結束時,所有線程都會強制結束
thread
模塊函數
start_new_thread(function, args,kwargs=None): 產生新的線程,args是function的參數,沒有時寫(),kwargs用來調用這個函數
allocate_lock(): 分配鎖,LockType類型
exit(): 讓線程退出
LockType的操作
acquire(wait=None):嘗試獲取鎖
locked(): 獲取了鎖返回True,沒有返回False
release():釋放鎖
Demo1
$ cat t1.py
import thread
from time import sleep
def a():
print "a start"
sleep(2)
print "a end"
def b():
print "b start"
sleep(2)
print "b end"
def main():
thread.start_new_thread(a,())
thread.start_new_thread(b,())
print "all done"
if __name__ == "__main__":
main()
$ python t1.py
all done
b start
a start
最終會發現,每一次運行出來的結果都有可能不同,但是絕對不會出現“a end”和“b end”。這是為什么呢,這里沒有寫讓主線程停下來等所有子線程結束后再繼續運行的代碼,所以main線程在執行完print "all done"就關閉了a和b兩個線程。怎么辦呢,可以在這里加一個sleep等待子進程執行完畢后再退出。
Demo2: thread -- 多線程的演示 by sleep
$ cat t2.py
import thread
from time import sleep
def a():
print "a start"
sleep(2)
print "a end"
def b():
print "b start"
sleep(2)
print "b end"
def main():
thread.start_new_thread(a,())
thread.start_new_thread(b,())
sleep (4) ----防止主進程過早退出,加sleep等待子進程執行完畢后再推出
print "all done"
if __name__ == "__main__":
main()
$ python t1.py
b start
a start
a end
b end
all done
但是假設我們不知道子進程執行的時間怎么辦,這就是鎖的用武之地了。因為使用鎖要比使用sleep()函數更為合理。如下所示:
Demo3: thread -- 多線程演示 by lock
實現方式為: 主線程初始化兩個鎖,分別傳給兩個函數,兩個函數在執行完自己的代碼后釋放鎖,主線程一直在輪詢這個鎖有沒有釋放,如果釋放了就退出。
def a(lock, nsec):
print "a starting at :", ctime()
sleep(nsec)
lock.release() -- 執行完之后釋放鎖
print "a end", ctime()
def b(lock, nsec):
print "b starting at :", ctime()
sleep(nsec)
lock.release() -- 執行完之后釋放鎖
print "b end", ctime()
def main():
print "Demo Starting at:", ctime()
locks = []
# Initialize lock -- 主線程先獲取兩個鎖,占為己有
for i in range(2):
lock = thread.allocate_lock()
lock.acquire()
locks.append(lock)
# 每個進程分配一個鎖
thread.start_new_thread(a, (locks[0],2))
thread.start_new_thread(b, (locks[1],4))
for i in range(2): #一直在輪詢,看鎖有沒有釋放
while locks[i].locked(): pass
print "all done at:", ctime()
最后的結果為:
$ python thread_demo.py
Demo Starting at: Fri Aug 29 22:03:01 2014
a starting at : Fri Aug 29 22:03:01 2014
b starting at : Fri Aug 29 22:03:01 2014
a end Fri Aug 29 22:03:03 2014
b end Fri Aug 29 22:03:05 2014
all done at: Fri Aug 29 22:03:05 2014
不難發現,thread庫的同步機制比較難用,一切都需要主進程來處理。并且沒有守護進程,主進程一退,整個世界都會變得很清靜。而threading庫給我們提供了守護進程。下面就來看看threading的簡單用法。
threading
threading提供了Thread類,還提供了很多非常好用的同步機制。感覺重點了解Thread類就可以,多線程,也就是通過Thread類的多個實例。 類的主要方法有:
start():開始線程的執行。thread庫里里面,是沒有辦法控制線程的開始的
join(timeout=None): 等待線程結束,有點類似Demo3中的輪詢
run():定義線程的功能
感覺上面是比較重要的,立馬就會用到的。還有一些其他的:
getName():獲取線程名
setName(name):設置線程名
isAlive(): 返回bool 表示線程是否在運行中
activeCount():返回運行中的線程數
currentThread():返回當前線程對象
enumerate():返回當前活動線程的列表
isDaemon(): 返回線程的Daemon標志
setDaemon(daemonic): 設置線程的Daemon標志,一般在start()函數前調用
settrace(func):為所有線程設置跟蹤函數
setprofile(func): 為所有線程設置profile函數
Demo4 -- threading演示
def loop(i, nsec):
print "thread %d starting at : %s" %(i, ctime())
sleep(nsec)
print "thread %d end at : %s" %(i, ctime())
def main():
threads = []
loops = [2, 4]
# 實例化進程
for i in range(len(loops)):
t = threading.Thread(target = loop, args = (i, loops[i]))
threads.append(t)
for i in range(len(loops)):
threads[i].start()
for i in range(len(loops)):
threads[i].join()
print "all done"
最后的結果為:
thread 0 starting at : Sun Aug 31 13:31:28 2014
thread 1 starting at : Sun Aug 31 13:31:28 2014
thread 0 end at : Sun Aug 31 13:31:30 2014
thread 1 end at : Sun Aug 31 13:31:32 2014
all done
對Daemon線程理解:
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.
線程可以被標識為"Daemon線程",Daemon線程表明整個Python主程序只有在Daemon子線程運行時可以退出。該屬性值繼承自父線程,可通過setDaemon()函數設定該值。
Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
注意:Daemon線程會被粗魯的直接結束,它所使用的資源(已打開文件、數據庫事務等)無法被合理的釋放。因此如果需要線程被優雅的結束,請設置為非Daemon線程,并使用合理的信號方法,如事件Event。
Python主程序當且僅當不存在非Daemon線程存活時退出。
即:主程序等待所有非Daemon線程結束后才退出,且退出時會自動結束(很粗魯的結束)所有Daemon線程。
亦理解為:Daemon設置為子線程是否隨主線程一起結束,默認為False。如果要隨主線程一起結束需要設置為True。
Daemon線程用途:
Daemons are only useful when the main program is running, and it's okay to kill them off once the other non-daemon threads have exited. Without daemon threads, we have to keep track of them, and tell them to exit, before our program can completely quit. By setting them as daemon threads, we can let them run and forget about them, and when our program quits, any daemon threads are killed automatically.
Daemon線程當且僅當主線程運行時有效,當其他非Daemon線程結束時可自動殺死所有Daemon線程。如果沒有Daemon線程的定義,則必須手動的跟蹤這些線程,在程序結束前手動結束這些線程。通過設置線程為Daemon線程,則可以放任它們運行,并遺忘它們,當主程序結束時這些Daemon線程將自動被殺死。
轉載于:https://www.cnblogs.com/niansi/p/7441582.html
總結
以上是生活随笔為你收集整理的python多线程理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [js高手之路]原型对象(prototy
- 下一篇: Python学习笔记(四十六)网络编程(