【问题标题】:Python: Can't start new thread. <100 active threadsPython:无法启动新线程。 <100 个活动线程
【发布时间】:2015-08-29 05:27:33
【问题描述】:

我收到以下错误:

----- Match 93028: ------ Patch 5.11 ------78 Threads Active
----- Match 93029: ------ Patch 5.11 ------77 Threads Active
----- Match 93030: ------ Patch 5.11 ------76 Threads Active
----- Match 93031: ------ Patch 5.11 ------71 Threads Active
----- Match 93032: ------ Patch 5.11 ------55 Threads Active
----- Match 93033: ------ Patch 5.11 ------56 Threads Active
----- Match 93034: ------ Patch 5.11 ------57 Threads Active
----- Match 93035: ------ Patch 5.11 ------58 Threads Active
----- Match 93036: ------ Patch 5.11 ------59 Threads Active
Traceback (most recent call last):
  File "pulldata.py", line 91, in <module>
    getPatchData('5.11', '511')
  File "pulldata.py", line 64, in getPatchData
    matchThread.start()
  File "/usr/lib/python3.4/threading.py", line 850, in start
    _start_new_thread(self._bootstrap, ())
RuntimeError: can't start new thread

这通常是由于打开的线程过多造成的,但正如您所见,我还打印了活动线程的数量。有

slot = threading.BoundedSemaphore(value=1000)
def getMatchData(index,match,patch):
    global requestsSent
    global logfile
    print("----- Match {0}: ------ Patch {1} ------{2} Threads Active".format(index,patch,threading.active_count()))
    logfile.write("Parsing Match {0} for patch {1}:\n".format(index,patch))

    #match is a class. get is a function that sends a request to the server and returns a request object from where I get the json response.
    data = match.get().json()

    #processdata

    slot.release()

def getPatchData(patch, name):
    global logfile
    threads = []
    matches = getAllMatches(patch)
    for index, match in enumerate(matches):
        slot.acquire()
        matchThread = threading.Thread(target=getMatchData, args=(index,match,patch))
        threads.append(matchThread)
        matchThread.start()
        for t in threads:
            if not t.isAlive():
                threads.remove(t)

    for t in threads:
        t.join()

插槽信号量应该限制活动线程的数量,但我认为我从来没有达到 1000 个线程。在我假设这个错误是由于我的线程数组指向的线程引起的,所以我添加了代码以在它们不再处于活动状态时将它们从数组中删除。

我不明白为什么只有 59 个活动线程时无法启动新线程。

另外,有没有更好的方法来实现我想要做的事情?每个线程向 API 发送一个请求。我尝试在没有并发的情况下执行此操作,但我什至没有接近我的速率限制。

【问题讨论】:

标签: python multithreading


【解决方案1】:

我遇到了类似的问题,我是这样解决的。

不确定 OP 使用的是什么操作系统,但在 Linux 上,每个用户的进程数通常有限制。 您可以使用ulimit -u(或ulimit -a)查看它。 这个定义有点用词不当,因为限制实际上是 OS 线程数(或 LWP)。 (请参阅接受的答案:https://superuser.com/questions/376532/does-gnu-linux-counts-processes-and-threads-together-when-i-limit-their-number

在我的系统上,限制似乎设置为 400(但管理员可以更改)。

您可以使用以下命令查看所有线程的列表:

ps -fLu &lt;your_username&gt;

在我的情况下,我的 python 应用程序会引发与 OP 报告的相同的异常,但 threading.active_count() 会返回 7。

原来我有很多以前会话的剩余进程(我对nohup...有点太热衷了​​),每个都有几个线程,挂在系统中。删除它们摆脱了线程创建错误。

【讨论】:

  • 你是怎么找到挂线的?我们面临着类似的情况。
【解决方案2】:

我在类似的情况下运行,但我的进程需要运行很多线程。

我用命令统计了线程数:

ps -fLu user | wc -l

显示 4098。

我切换到用户并查看系统限制:

sudo -u myuser -s /bin/bash

ulimit -u

得到 4096 作为响应。

所以,我编辑了 /etc/security/limits.d/30-myuser.conf 并添加了以下行:

myuser hard nproc 8192

myuser soft nproc 8192

重新启动服务,现在它以 7017 个线程运行。

附言。我有一个 32 核的服务器,我正在使用此配置处理 18k 个同时连接。

【讨论】:

    猜你喜欢
    • 2021-01-13
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多