【问题标题】:Python: threads can only be started oncePython:线程只能启动一次
【发布时间】:2016-04-29 11:51:12
【问题描述】:

我想在 python 中做线程。我有 100 个单词,想把它们放在 6 个不同的链接中。如果其中一个链接准备好,我希望该链接可以获取新单词。这虽然其他线程仍然在工作中的第一个词。完成 100 个关键字后,应该允许我的完整程序先执行更多代码。我有以下代码:

threads = []

def getresults(seed):
    for link in links:
        t = threading.Thread(target=getLinkResult, args = (suggestengine, seed))
        threads.append(t)
    for thread in threads:
        thread.start()

for seed in tqdm:
    getresults(seed + a)
    getresults(seed + b)

for thread in threads:
    thread.join()

#code that should happen after

我现在收到一个错误: 线程只能启动一次

【问题讨论】:

  • 请发布您的错误
  • @Kasramvd 使用此代码我收到错误“线程只能启动一次”如何更改我的代码以使一切正常?
  • @GilbertAllen RuntimeError: 线程只能启动一次

标签: python multithreading


【解决方案1】:

您调用了两次getresults,两次都引用了同一个全局threads 列表。这意味着,当您第一次调用 getresults 时,线程会启动。

当您第二次调用它们时,之前已经运行的线程会再次调用.start() 方法。

您应该将getresults 中的线程作为本地线程启动,然后将它们附加到全局threads 列表中。

尽管您可以执行以下操作:

for thread in threads:
    if not thread.is_alive():
        thread.start()

它不能解决问题,因为一个或多个线程可能已经结束并因此重新启动,因此会导致相同的错误。

【讨论】:

  • 如果我更改我的代码,以便每个线程的 thread.join 在得到结果之后我会得到相同的错误
  • @Sonius 试试我的建议,看看它是否有效。它可能应该。
  • 我再试一次。但现在我得到了按摩:“列表”对象没有属性“is_alive”
  • @Sonius 应该是 thread.is_alive 而不是 threads。我的错误,已更正。
【解决方案2】:

您应该只在 getresults 中启动新线程

threads = []

def getresults(seed):
  local_threads = []
  for link in links:
      t = threading.Thread(target=getLinkResult, args = (suggestengine, seed))
      local_threads.append(t)
      threads.append(t)
  for thread in local_threads:
      thread.start()

for seed in tqdm:
  getresults(seed + a)
  getresults(seed + b)

for thread in threads:
        thread.join()

【讨论】:

  • 这是我第一次拥有的。但是我只能在 5 个线程中做 1 个单词。如果所有 5 个线程都准备好了,我可以做下一个词。但是通过 Games Brainic 的解决方案,第三个单词可能在线程 1 中,而线程 2 仍然在单词 1 上工作 :)
【解决方案3】:

最快的方式,但不是最聪明的(一般问题):

from tkinter import *
import threading, time

def execute_script():
    def sub_execute():
        print("Wait 5 seconds")
        time.sleep(5)
        print("5 seconds passed by")
    threading.Thread(target=sub_execute).start()

root = Tk()
button_1 = Button(master=root, text="Execute Script", command=execute_script)
button_1.pack()
root.mainloop()

【讨论】:

  • 我喜欢你为节目添加 GUI 到答案中的方式。
【解决方案4】:

错误是明确的。您启动线程两次,而您不应该这样做。

getresults(seed + a)
getresults(seed + b)

当您对这些调用进行排序时,您会启动两次线程循环。要正确地做你想做的事,你可以创建一个thread pool and a task queue。基本上,您需要第二个要处理的单词列表和一个互斥锁。每个线程都会锁定互斥体,读取一个单词并将其出队,然后解锁并处理该单词。

【讨论】:

  • 虽然你的回答很好,但它并没有达到用户的目的。用户想要批量调用线程,即需要重新启动相同的线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
  • 2015-03-24
  • 2022-07-09
相关资源
最近更新 更多