【问题标题】:python thread inside a loop causing runtime error ( join() not waiting for thread to end?)循环内的python线程导致运行时错误(join()不等待线程结束?)
【发布时间】:2017-06-15 22:34:37
【问题描述】:
import time
from threading import Thread

def s_process():
    print('***********************************************')
    ##time.sleep(2)
    print('###############################################')
    ##time.sleep(2)
    return

a = Thread(target=s_process)

while(True):
    a.start()
    a.join()
    a.start()
    a.join() 

为什么这段代码会导致错误

***********************************************
###############################################
Traceback (most recent call last):
  File "xxxxxxxxxxxxxxxxxxxxx", line 16, in <module>
    a.start()
RuntimeError: threads can only be started once

不应该 join() 等到线程完成。如果我误解了 join() 的工作原理,我应该如何在不使用超时的情况下等待线程完成

【问题讨论】:

  • 把你的代码改成这个 ** while(True): a = Thread(target=s_process) a.start() a.join() **
  • 错误不在join 行,它在start 行。这对我来说似乎不言自明:不要在同一个对象上调用start 两次。如果需要,创建一个新的线程对象。
  • 您只定义了 1 个线程 a 并且您已经开始并调用了它的 join() 方法。无法重新开始!
  • 创建这么多线程对象安全吗?他们会弄乱内存使用吗?还是在完成后清理干净
  • 所以线程使用相同的内存占用,而进程有自己的占用。全局解释器锁(或 GIL)一次只允许一个线程执行 Python 字节码(除非它的 I/O 然后大部分绕过 GIL)。我建议阅读thisthat 以获得更深入的知识。

标签: python multithreading


【解决方案1】:

这应该有效:

import time
from threading import Thread

def s_process():
    print('***********************************************')
    ##time.sleep(2)
    print('###############################################')
    ##time.sleep(2)
    return

while(True):
    a = Thread(target=s_process)
    a.start()
    a.join()
    del a           #deletes a

【讨论】:

  • 创建这么多线程对象安全吗?他们会弄乱内存使用吗?还是在完成后清理干净
  • **del a ** 将清理
  • 但此方法一次创建 1 个线程。那么创建1个线程有什么意义呢?为什么不直接打电话给s_process
【解决方案2】:

要启动多个线程,请构建threading.Thread 对象列表并使用for 循环迭代它们的start()join() 方法,如下所示:

import time
from threading import Thread

def s_process():
    print('***********************************************')
    time.sleep(2)
    print('###############################################')
    time.sleep(2)
    return

# list comprehension that creates 2 threading.Thread objects
threads = [Thread(target=s_process) for x in range(0, 2)]

# starts thread 1
# joins thread 1
# starts thread 2
# joins thread 2
for thread in threads:
    try:
        thread.start()
        thread.join()
    except KeyboardInterrupt: # std Python exception
        continue # moves to next thread iterable

编辑: 包含try/exceptKeyboardInterrupt 并使用通用Ctrl+X+C 进行测试。

【讨论】:

  • 我需要循环相同的代码,而不会在执行表单 KeyboardInterrupt 中被中断
猜你喜欢
  • 1970-01-01
  • 2012-07-13
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多