如何让线程使用下一个尚未使用的对象? [英] How to have a thread use the next object not already used?

查看:29
本文介绍了如何让线程使用下一个尚未使用的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可能正在尝试将 threading 用于我不应该使用的东西,如果是这样,请告诉我.

It's possible I might be trying to use threading for something I shouldn't be, if so please let me know.

我制作了一个较小的代码示例,以便更容易理解我想要什么.

I made a smaller example of my code so it's simpler to understand what I'd like.

我让用户输入 IP 地址,然后我 ping 他们输入的 IP 地址.我想一次 ping x 个 IP 地址,在这个例子中是 4 个.

I'm having users input IP addresses, then i'm pinging the IP addresses they entered. I'd like to ping x number of IP addresses at a time, in this example its 4.

问题是每个线程都 ping 了所有 4 个 IP 地址.我想要 1 个线程 ping IP 1,然后另一个线程 ping IP 2,然后如果线程 1 被 IP 1 捕获,它会移动到下一个可用 IP(因此,如果线程 2 获取 IP 3,则线程 1 将获取IP4).

The issue is that each thread pings all 4 IP addresses. I'd like 1 thread to ping IP 1, then another to ping IP 2, then if thread 1 is fished with IP 1 it moves to the next available IP (so if thread 2 picked up IP 3, then thread 1 would pick up IP4).

这样我可以在大约 2 秒内 ping 所有 IP 地址,而不是大约 4 秒.

This way I can ping all IP addresses in ~2 seconds, rather than ~4 seconds.

如果您需要更多详细信息,请告诉我.

Let me know if you need more details.

import threading
#prints out "pinging IP" for each IP in ip_list
def _ping(ip_list):
    for objects in ip_list:
        print ("Pinging ip: " + objects)

ip_list = []

#ask user for IP address, appends to ip_list
for x in range (0,4):
    ip = str(input("please enter ip: "))
    ip_list.append(ip)

#calls function _ping with threading.
if __name__ == '__main__':
    numOfThreads = 2
    threadList = []
    for i in range (numOfThreads):
        t = threading.Thread(target=_ping, args=(ip_list[0:4],))
        t.start()
        threadList.append(t)

输出为:

please enter ip: 1
please enter ip: 2
please enter ip: 3
please enter ip: 4
Pinging ip: 1
Pinging ip: 2
Pinging ip: 3
Pinging ip: 4
Pinging ip: 1
Pinging ip: 2
Pinging ip: 3
Pinging ip: 4

推荐答案

队列是一种很好的数据结构,可以帮助解决这个问题.队列是先进先出 (FIFO) 列表,这意味着项目将按照放入其中的顺序从队列中移除.Python 标准库中的 queue 模块实现了一个线程安全队列,正是您所需要的.

A queue is a good data structure to help solve this. Queues are first-in, first-out (FIFO) lists, meaning that items are removed from it in the order in which they are put into it. The queue module in Python's standard library implements a thread-safe queue, exactly what you need.

您可以让主线程将所有 IP 放入队列,然后每个线程将从队列中出列.这将删除该项目,以便线程仅在尚未处理的情况下获得 IP.这只需对您现有的代码稍作修改.

You can have the main thread place all the IPs into the queue, then each thread will dequeue from it. This will remove the item, so that threads only get an IP if it's not already been processed. This will require only a slight modification to your existing code.

最重要的变化是,当没有更多元素要处理时,您需要某种方式关闭线程.最常见的方法是添加一个哨兵",一些通知线程关闭的对象.None 是一个常见的选择,空字符串也是如此.

The most important change is that you need some way of shutting the threads down when there are no more elements to process. The most common way to do this is to add a "sentinel", some object which notifies the thread to shutdown. None is a common choice, as is an empty string.

import threading
import queue

def _ping(ip_queue):
    while True:
        ip = ip_queue.get()
        if ip is None: # Loop until sentinel encountered
            return
        print("Pinging ip: " + ip)

# Construct a queue, rather than a simple list
ip_queue = queue.Queue()

# Ask user for IP address, place onto queue
for x in range (4):
    ip = input("please enter ip: ") # No need for str(), input() already returns a string
    ip_queue.put(ip)

# Calls function _ping with threading.
if __name__ == '__main__':
    numOfThreads = 2
    threadList = []

    # Place sentinels for each thread
    for i in range(numOfThreads):
        ip_queue.put(None)

    # Start each thread
    for i in range (numOfThreads):
        t = threading.Thread(target=_ping, args=(ip_queue,))
        t.start()
        threadList.append(t)

    # Usually good practice to wait for each thread
    for thread in threadList:
        thread.join()

这篇关于如何让线程使用下一个尚未使用的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆