2014-02-09 3 views
3

версия Python: "2.7.3 (по умолчанию, 10 апреля 2013, 6:20:15) \ п [GCC 4.6.3]Количество активных потоков

У меня есть это:

#!/usr/bin/env python 
import time, threading, os 
def f1(arg1): 
    for i in xrange(arg1): 
     time.sleep(1) 
     print "i is: ", i 
     print threading.active_count() 
     print threading.enumerate() 

if __name__ == '__main__': 

    t = threading.Thread(name="MyThread1", target=f1, args=(5,)) 
    t.start() 

Мой вопрос: почему количество активных потоков сообщается как 2 и почему список, сгенерированный enumerate, также содержит основной поток.

Я думал, что основная нить прекращается после нереста «MyThread1».

$ ./threadeg.py

i is: 0 
2 
[<_MainThread(MainThread, stopped 139858183157504)>, <Thread(MyThread1, started 139858153768704)>] 

i is: 1 
2 
[<_MainThread(MainThread, stopped 139858183157504)>, <Thread(MyThread1, started 139858153768704)>] 

i is: 2 
2 
[<_MainThread(MainThread, stopped 139858183157504)>, <Thread(MyThread1, started 139858153768704)>] 

i is: 3 
2 
[<_MainThread(MainThread, stopped 139858183157504)>, <Thread(MyThread1, started 139858153768704)>] 

i is: 4 
2 
[<_MainThread(MainThread, stopped 139858183157504)>, <Thread(MyThread1, started 139858153768704)>] 
+2

Основной поток не заканчивается, пока существуют другие потоки не-демона. – Cairnarvon

+1

@Cairnarvon Каков источник вашей справки, на основе которого вы делаете заявление? Могу я, пожалуйста, знать? – abc

ответ

1

threading.activeCount(), которая возвращает количество потоков активных (которые были начаты с этим модулем). [Source]

Поскольку модуль нарезание резьбы является чистым модулем питона построен на верхней части модуля нити, это довольно легко, чтобы просмотреть исходный код.

Вот исходный код для active_count

def activeCount(): 
    """Return the number of Thread objects currently alive. 

    The returned count is equal to the length of the list returned by 
    enumerate(). 

    """ 
    with _active_limbo_lock: 
     return len(_active) + len(_limbo) 

при дальнейшем исследовании следует отметить, что существует _MainThread экземпляр хранится в _active (_active и _limbo являются словарями, что имена карты нити в их случаи) , И удаляется из _active, когда вызывается _exitfunc.

Вот источник _MainThread,

class _MainThread(Thread): 

    def __init__(self): 
     Thread.__init__(self, name="MainThread") 
     self._Thread__started.set() 
     self._set_ident() 
     with _active_limbo_lock: 
      _active[_get_ident()] = self 

    def _set_daemon(self): 
     return False 

    def _exitfunc(self): 
     self._Thread__stop() 
     t = _pickSomeNonDaemonThread() 
     if t: 
      if __debug__: 
       self._note("%s: waiting for other threads", self) 
     while t: 
      t.join() 
      t = _pickSomeNonDaemonThread() 
     if __debug__: 
      self._note("%s: exiting", self) 
     self._Thread__delete() 

раз _exitfunc называется _MainThread ожидает для всех не нитей демона, чтобы присоединиться, а затем вызывает Thread._delete, который в данном случае был mangled к __Thread_delete, который, в свою очередь снимает _MainThread от словарь _active.

_exitfunc присваивается _shutdown на линии 1201.

_shutdown = _MainThread()._exitfunc 

_shutdown вызывается из pythonrun.c, который, в свою очередь, вызывается Py_Finalize. Py_Finalize вызывается Py_Exit, который выходит из основного процесса (в этот момент остаются только демоны).

Py_Exit's documentation.

Выход из текущего процесса. Это вызывает Py_Finalize(), а затем вызывает выход функции стандартного C-библиотеки (status).

Вот пример того, как вы себя чувствуете.

import threading, time 

def f(): 
    time.sleep(1) #wait for the interpreter to "shutdown" 
    print threading.enumerate() 

if __name__ == '__main__': 

    t = threading.Thread(target=f) 
    t.daemon = True 
    t.start() 

    threading._shutdown() #simulate an interpreter shutdown 

Другой большой answer описывает, как потоки выключения.

Смежные вопросы