从队列中弹出唯一项并在多个线程中使用

时间:2017-03-03 06:43:21

标签: python multithreading python-2.7 queue

我不明白如何让每个线程从队列中弹出一个唯一的项目并同时运行该函数。它当前编写的方式是线性运行,通过从队列中弹出相同的项来运行两个线程。

我怎么能让循环将队列中的唯一项传递给每个线程?

import sys
import subprocess
import threading
import Queue

def pinger(host):
    subprocess.Popen(['ping', '-c 1', '-W 1', host])

ping_hosts = ['google.com', 'yahoo.com', 'disney.com', 'myspace.com','www.pingler.com', 'www.pingmylink.com',
'www.pingoat.net' ,'www.blogsearch.google.com' ,'pingmyblog.com', 'www.twingly.com', 'www.weblogs.com', 'auto-ping.com' ]

ping_hosts = [ 'google.com', 'yahoo.com', 'disney.com']

def Main():
    q = Queue.Queue()
    for item in ping_hosts:
        q.put(item)

    while q.qsize() != 0:
        host = q.get()
        t1 = threading.Thread(target=pinger, args=(host,)
        t2 = threading.Thread(target=pinger, args=(host,)
        t1.start()
        t2.start()
        t1.join()
        t2.join()

    print "Main Completed"

if __name__ == '__main__':
    Main()

1 个答案:

答案 0 :(得分:0)

您的工作线程会ping同一主机,因为您为它们提供了相同的主机值。但是代码的主要问题是您在主(单个)线程中使用队列。你所做的是将任务放入队列(主线程),然后获取它们(主线程)并启动两个工作线程,执行ping(线程1,线程2),然后连接它们(再次返回主线程)和在队列中有任务时执行此操作。

此外,popen实际上启动了一个新进程来执行ping,因此如果只有您感兴趣的ping,您甚至可能不需要线程,只是:

for host in ping_hosts:
    subprocess.Popen(['ping', '-c 1', '-W 1', host])

但假设您的问题是关于线程,而不是ping ... 在使用队列时,通常将任务(数据)放在一个线程中,称为"生成器",并在另一个线程中获取和处理任务(数据),称为" consumer&# 34;,同时运行。当然可能有几个生产者和几个消费者。

因此,在您的情况下,您想要的是:将主机放入队列(主线程),启动工作线程,这将从队列(线程1,线程2)获取数据并处理它(相同的线程1 ,线程2),同时运行。

试试这样:

import subprocess
import threading
import Queue


def ping(host):
    """Pings a host."""
    print("Pinging '%s'" % host)
    subprocess.Popen(['ping', '-c 1', '-W 1', host])


def pinger_thread(thread_name, task_queue):
    """Gets the data from the queue and processes it."""
    while task_queue.qsize() != 0:
        host = task_queue.get()
        print("%s: pinging '%s'" % (thread_name, host))
        ping(host)


def main():
    ping_hosts = ['google.com', 'yahoo.com', 'disney.com']

    # Fill the queue
    q = Queue.Queue()
    for item in ping_hosts:
        q.put(item)

    # Start the threads, that will consume data from the queue
    t1 = threading.Thread(target=pinger_thread, args=("Thread 1", q))
    t2 = threading.Thread(target=pinger_thread, args=("Thread 2", q))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("Main Completed")


if __name__ == '__main__':
    main()

输出:

python2 test.py 
Thread 1: pinging 'google.com'
Pinging 'google.com'
Thread 2: pinging 'yahoo.com'
Pinging 'yahoo.com'
Thread 1: pinging 'disney.com'
Pinging 'disney.com'
Main Completed
PING google.com (74.125.232.231) 56(84) bytes of data.
PING yahoo.com (206.190.36.45) 56(84) bytes of data.
PING disney.com (199.181.131.249) 56(84) bytes of data.
...
--- google.com ping statistics ---
...
--- disney.com ping statistics ---
...
--- yahoo.com ping statistics ---
...

我删除了一些ping命令输出无关紧要。但重要的是,您可以看到主机按顺序由两个线程处理。