活跃线程数量

3

Python版本:'2.7.3(默认,Apr 10 2013,06:20:15)\n [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 您所陈述的依据来源是什么?我可以知道吗? - Ankur Agarwal
1个回答

1

threading.activeCount() 返回活跃线程的数量(使用该模块启动的线程)。[来源]

由于 threading 模块是在 thread 模块基础上构建的纯 Python 模块,因此查看源代码非常容易。

这里是 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)

进一步调查发现应该注意到,在_active中存储了_MainThread实例(_active和_limbo都是将线程名称映射到其实例的字典)。并且在调用_exitfunc时从_active中删除。
以下是_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。在这种情况下,Thread._delete已被替换为mangled,即__Thread_delete,进而将_MainThread_active字典中删除。

第1201行将_exitfunc赋给了_shutdown

_shutdown = _MainThread()._exitfunc

_shutdown 是从 pythonrun.c 调用的,而该函数又被 Py_Finalize 调用。Py_Exit 调用了 Py_Finalize,然后退出主进程(此时只剩下守护进程)。

Py_Exit 的文档

退出当前进程。这将调用 Py_Finalize() 然后调用标准 C 库函数 exit(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

另一篇很棒的答案,描述了如何关闭线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接