在Python中的每个线程中建立多个套接字连接,在3个连接后卡住?

问题描述 投票:0回答:1

我有一个包含用户名/主机信息的对象字典,用于连接到服务器,并希望每个连接都在它自己的线程中运行,但无论我是否尝试,似乎最多只能从 100 个测试对象中获得 3 个正确连接使用concurrent.futures或threading模块。我知道这与当前线程在前一个线程完成之前执行有关,因为我设法通过在每个连接之间休眠 2 秒来将一个用户连接到 3 个用户,但这当然不是一个手动处理的可行解决方案,加上我注意到将睡眠时间增加到 5 秒或更多秒仍然只能连接 3 个用户,这让我想也许还有另一个问题?

我一直在玩弄 executor.shutdown 的 wait-keyword ,但没有真正理解它,但运气不好,在某处读到该问题可能与 GIL 有关,但根据其他来源,这不会影响我想做的事情,就我个人而言,除了运行多处理而不是线程之外,我根本不知道有什么方法可以解决这个问题。

number_of_objs = 100

def run_(obj):
     obj.connect()

objs = {}

for i in range(number_of_objs):
     nickname = f"{nickname_prefix}_{i}"
     hostname = "server.example.com"
     port = 1234
     objs[i] = CreateObjs(nickname, hostname, port)

with concurrent.futures.ThreadPoolExecutor() as executor:
    for k in objs.keys():
        time.sleep(2)
        executor.submit(run_, objs[k])

# Result:
# Testuser_0 successfully connected to server.example.com at port 1234
# Testuser_1 successfully connected to server.example.com at port 1234
# Testuser_2 successfully connected to server.example.com at port 1234
python multithreading concurrent.futures
1个回答
0
投票

如果我猜对了你的意图,

ThreadPoolExecutor
在这里不是正确的结构。我们先来测试一下下面的非并发代码:

for k in objs.keys():
    run_(objs[k])

此代码应按顺序建立连接,并且下一个连接应在前一个连接结束后开始。如果您想使用

ThreadPoolExecutor
,此代码应该可以工作。

ThreadPoolExecutor
实际上所做的是,它同时运行多个任务,如果任务数量大于worker数量,则其余任务会排队等待前面的任务结束。 GIL 的问题是,如果任务仅包含计算,则
ThreadPoolExecutor
无法按预期运行,因为由于 GIL,它们无法以真正的多线程方式运行。现在,如果
run_
中的任务开始等待远程服务器,开始发送测试日期或类似的内容,
ThreadPoolExecutor
将不起作用,因为第一个任务永远不会结束。

如果希望启动 100 个并行线程来执行一些 I/O,则应该使用:

for k in objs.keys():
    threading.Thread(target=run_, args=(objs[k],)).start()

注意:您不能像这样启动任意数量的线程。 100 就可以了,也可能是 1000,但是活动线程的数量有实际限制。

© www.soinside.com 2019 - 2024. All rights reserved.