【问题标题】:Using Threading and Queue in infinite loop does not close threads在无限循环中使用线程和队列不会关闭线程
【发布时间】:2023-03-14 19:35:02
【问题描述】:

我正在努力让 python 定期运行一些线程函数并关闭线程(或重用相同的线程而不产生新的线程)。运行下面的代码时,每次运行函数时都会产生新线程,最终程序会一起崩溃/停止。

任务完成后是否可以关闭线程?

import threading
from Queue import Queue
import time
import socket

number_of_threads = 10

def check_server(address):
    s = socket.socket()
    s.settimeout(1)
    try:
        s.connect((address, 443))
        return True
    except:
        return False

def get_online_servers(subnet):
    def threader():
        while True:
            global online_servers
            ip = q.get()
            a = check_server(ip)
            if a:
                online_servers.append(ip)
            q.task_done()

    q = Queue()

    for x in range(number_of_threads):
        t = threading.Thread(target=threader)
        t.daemon = False
        t.start()

    for i in range(1, 20):
        ip = "{}.{}".format(subnet, i)
        q.put(ip)

    q.join()

    return online_servers

if __name__ == '__main__':
    while True:
        online_servers = []
        result = get_online_servers("10.0.0")
        print result
        time.sleep(5)

【问题讨论】:

    标签: python multithreading python-2.7 python-multithreading


    【解决方案1】:

    线程在完成其功能时会自动完成。 (您通常希望将线程对象和join 保留在某个地方,但这与您的问题无关。)

    那么,如果你想让它们在每项任务之后完成,你为什么要在函数中放置一个while True: 循环?只需取出,一切都会按照您的要求进行。

    让线程运行无限循环直到队列完成(然后break/return)可能很有用,但这是一种不同的设计。对于该设计,您只想在启动时启动 10 个线程,而不是为每个请求启动一批新线程。 (虽然在这种情况下,您只是在构建一个沼泽标准线程池,因此使用 stdlib 中已经存在的线程池或稍高级别的concurrent.futures.ThreadPoolExecutor 可能更容易。)

    最后,如果您真的想要为每批请求创建一个包含 10 个线程的新池,您可以这样做。这基本上是两种选择的所有复杂性,没有任何优势,但它是可行的。就像在持久线程池中一样,您需要更改线程函数以在队列完成时退出。而且您可能需要将所有 10 个线程保留在一个列表中,并在加入队列后将它们全部加入。但这应该可行。

    【讨论】:

    • 谢谢,我不知道为什么我有一个while循环:/。但是,大多数线程现在(最终)都关闭了,但剩下的很少。所以在删除函数中的while循环后,在队列中我有20个IP地址要检查,前10个IP被检查,剩下2个线程并且程序无法继续!对不起,我是一个完全的菜鸟,但我正在尝试,并且是编程新手,事情并不那么明显。
    • @IlirB 您的目标是学习如何编写线程池,还是让您的代码正常工作?因为如果是后者,我强烈建议您删除现有代码并使用ThreadPoolExecutor 为您完成。但如果是前者,我们应该解决一些其他问题,然后再谈细节。如果没有整个循环,您的线程会按照您的要求退出,但现在您将只处理前 10 个作业。您要么需要为每个任务创建一个线程,要么将线程更改为循环直到完成,而不是永远循环或只做一项工作。
    • 公平点,答案是两者兼而有之,学习并让代码工作。我开始研究 ThreadPoolExecutor 并且看起来像我应该使用的模块。您指出了我的代码(while 循环)中的问题并让我朝着正确的方向前进,这对我来说很有价值。谢谢。
    猜你喜欢
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 2020-08-13
    • 2015-09-19
    • 2014-11-12
    相关资源
    最近更新 更多