久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

python 之美

 java_laq小館 2014-11-18

Python之美[從菜鳥到高手]--threading daemon線程原理解讀

分類: python 823人閱讀 評論(0) 收藏 舉報

事情的起因是我在看下面一段代碼遇到的疑惑,,明明是while True,為什么代碼沒有死循環(huán),??

  1. class D(threading.Thread):  
  2.     def __init__(self, queue):  
  3.         threading.Thread.__init__(self)  
  4.         self.queue = queue  
  5.     def run(self):  
  6.         while  True:  
  7.             url = self.queue.get()  
  8.             self.download_file(url)  
  9.             self.queue.task_done()  
  10.   
  11.     def download_file(self, url):  
  12.         h = urllib2.urlopen(url)  
  13.         f = os.path.basename(url)+'.html'  
  14.         with open(f,'wb') as f:  
  15.             while  True:  
  16.                 c = h.read(1024)  
  17.                 if not c:  
  18.                     break  
  19.                 f.write(c)  
  20.   
  21. if __name__ == "__main__":  
  22.     urls= ['http://www.baidu.com','http://www.sina.com']  
  23.     queue = Queue.Queue()  
  24.     for i in range(5):  
  25.         t = D(queue)  
  26.         t.setDaemon(True)  
  27.         t.start()  
  28.   
  29.     for u in urls:  
  30.         queue.put(u)  
  31.   
  32.     queue.join()  

之前一直簡單認為setDaemon就是設(shè)置為后臺線程而已,,沒有進一步去挖掘里面的含義,。

可問題的關(guān)鍵就是setDaemon,在底層的thread模塊中,,只要主線程結(jié)束了,,所有的其它線程都會結(jié)束,這很明顯,主線程結(jié)束python將銷毀運行時環(huán)境,,主線程肯定會被結(jié)束,。

threading模塊的線程setDaemon就是為了解決這個問題的,如果setDaemon(True),,那么和之前一樣,,主線程結(jié)束,所有子線程都將結(jié)束,。如果setDaemon(False),,主線程將等待該線程結(jié)束,等同于你調(diào)用線程的join方法,。

所以如果將上面的setDaemon注釋和修改為False,,那么程序?qū)⑺姥h(huán)。

其實我們并不推薦上面的做法,,上面做法有點線程池的味道,,但如果你看過一些python的線程池實現(xiàn),while True

循環(huán)中肯定有檢測退出語句,,因為在python的世界里言明比隱晦更加pythonic,。但很不幸的是,上面的代碼就來

自與<<編寫高質(zhì)量代碼:改善Python程序的91個建議>>,,我并沒有噴這本書,,但我覺得代碼舉例的確有待商榷。

你可能好奇,,setDaemon(False)是如何等同于線程join的呢,?,不急,,且聽我慢慢道來,。

未解決這個問題,threading模塊引入了_MainThread對象

  1. # Special thread class to represent the main thread  
  2. # This is garbage collected through an exit handler  
  3.   
  4. class _MainThread(Thread):  
  5.   
  6.     def __init__(self):  
  7.         Thread.__init__(self, name="MainThread")  
  8.         self._Thread__started.set()  
  9.         self._set_ident()  
  10.         with _active_limbo_lock:  
  11.             _active[_get_ident()] = self  
  12.   
  13.     def _set_daemon(self):  
  14.         return False  
  15.   
  16.     def _exitfunc(self):  
  17.         self._Thread__stop()  
  18.         t = _pickSomeNonDaemonThread()  
  19.         if t:  
  20.             if __debug__:  
  21.                 self._note("%s: waiting for other threads"self)  
  22.         while t:  
  23.             t.join()  
  24.             t = _pickSomeNonDaemonThread()  
  25.         if __debug__:  
  26.             self._note("%s: exiting"self)  
  27.         self._Thread__delete()  
  28.   
  29. def _pickSomeNonDaemonThread():  
  30.     for t in enumerate():  
  31.         if not t.daemon and t.is_alive():  
  32.             return t  
  33.     return None  
  34.   
  35. # Create the main thread object,  
  36. # and make it available for the interpreter  
  37. # (Py_Main) as threading._shutdown.  
  38.   
  39. _shutdown = _MainThread()._exitfunc  
其實_MainThread并沒有干什么事,,唯一的貢獻就是在threading模塊導入時創(chuàng)建了一個實例,并將_exitfunc
賦值給_shutdown函數(shù),。_exitfunc將收集所有非daemon且alive的線程,,并調(diào)用線程的join方法。哦,,原來是

_MainThread悄悄的在幕后奮斗著,,剩下的問題就是誰調(diào)用_shutdown函數(shù)的呢?

當python要銷毀運行時之前肯定會調(diào)用,,所以打開pythonrun.c,,你會發(fā)現(xiàn)如下函數(shù)

  1. /* Wait until threading._shutdown completes, provided 
  2.    the threading module was imported in the first place. 
  3.    The shutdown routine will wait until all non-daemon 
  4.    "threading" threads have completed. */  
  5. static void  
  6. wait_for_thread_shutdown(void)  
  7. {  
  8. #ifdef WITH_THREAD  
  9.     PyObject *result;  
  10.     PyThreadState *tstate = PyThreadState_GET();  
  11.     PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,  
  12.                                                   "threading");  
  13.     if (threading == NULL) {  
  14.         /* threading not imported */  
  15.         PyErr_Clear();  
  16.         return;  
  17.     }  
  18.     result = PyObject_CallMethod(threading, "_shutdown""");  
  19.     if (result == NULL)  
  20.         PyErr_WriteUnraisable(threading);  
  21.     else  
  22.         Py_DECREF(result);  
  23.     Py_DECREF(threading);  
  24. #endif  
  25. }  
原來是這家伙在搞鬼,,漲見識了,原來在C中還有調(diào)用py代碼的需求啊,。沒辦法啊,,誰讓threading模塊是純py
代碼呢!??!

來自:http://blog.csdn.net/yueguanghaidao/article/details/40088431

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多