Python穿线顺序

Python threading sequence

这是我 运行 测试 Python

线程序列的示例程序
import threading
import time
import logging
import random

logging.basicConfig(level=logging.DEBUG,
        format = '%(asctime)s (%(threadName)-10s) %(message)s')

def worker():
        t = threading.currentThread()
        pause = random.randint(1,10)
        logging.debug('sleeping %s', pause)
        time.sleep(pause)
        logging.debug('ending sleep')
        return

for i in range(3):
        t = threading.Thread(target=worker,name='t%s'%i)
        t.setDaemon(True)
        t.start()

main_thread = threading.currentThread()
for t in threading.enumerate():
        if t is main_thread:
                continue
        logging.debug('joining %s', t.getName())
        t.join()

这是一个程序的输出运行:

2016-11-22 12:59:12,052 (t0        ) sleeping 3
2016-11-22 12:59:12,052 (t1        ) sleeping 3
2016-11-22 12:59:12,052 (t2        ) sleeping 8
2016-11-22 12:59:12,052 (MainThread) joining t0
2016-11-22 12:59:15,055 (t0        ) ending sleep
2016-11-22 12:59:15,056 (MainThread) joining t2
2016-11-22 12:59:15,056 (t1        ) ending sleep
2016-11-22 12:59:20,054 (t2        ) ending sleep
2016-11-22 12:59:20,054 (MainThread) joining t1

请注意,加入顺序与枚举列表顺序或计时顺序都不一致。主线程的加入顺序应该调用t0 -> t1 -> t2线程序列,但是是to -> t2 -> t1.

这里发生了什么?

threading.enumerate() 没有说明它枚举线程的顺序。查看源代码,线程在两个 dict 中被跟踪,称为 _active_limbo。当你枚举的时候,你枚举了这些字典的键,它们的顺序是没有定义的。

以这种方式加入线程是有风险的。您考虑了主线程,但是如果您导入了一个为了自己的目的而使用后台线程的模块怎么办?相反,保留您自己的列表

import threading
import time
import logging
import random

logging.basicConfig(level=logging.DEBUG,
        format = '%(asctime)s (%(threadName)-10s) %(message)s')

def worker():
        t = threading.currentThread()
        pause = random.randint(1,10)
        logging.debug('sleeping %s', pause)
        time.sleep(pause)
        logging.debug('ending sleep')
        return

threads = []

for i in range(3):
        t = threading.Thread(target=worker,name='t%s'%i)
        t.setDaemon(True)
        t.start()
        threads.append(t)

for t in threads:
        logging.debug('joining %s', t.getName())
        t.join()

输出是

2016-11-22 15:16:51,230 (t0        ) sleeping 10
2016-11-22 15:16:51,232 (t1        ) sleeping 8
2016-11-22 15:16:51,233 (t2        ) sleeping 4
2016-11-22 15:16:51,234 (MainThread) joining t0
2016-11-22 15:16:55,235 (t2        ) ending sleep
2016-11-22 15:16:59,241 (t1        ) ending sleep
2016-11-22 15:17:01,234 (t0        ) ending sleep
2016-11-22 15:17:01,235 (MainThread) joining t1
2016-11-22 15:17:01,235 (MainThread) joining t2