如何为两个不同的队列创建并行运行的线程? - Python

时间:2017-08-14 03:47:50

标签: python multithreading queue

我有两个队列用于不同的任务,第一次抓取将开始抓取列表中的链接,然后它将生成更多链接以爬网到队列1,并且还将生成到队列2上的不同任务的新链接,我的程序正在运行,但问题是:当队列2的工作人员开始运行时,它会从队列中停止工作人员,他们基本上没有并行运行,他们正在等待彼此完成任务。如何让它们并行运行?

import threading
from queue import Queue

queue = Queue()
queue_two = Queue()

links = ['www.example.com', 'www.example.com', 'www.example.com',
         'www.example.com', 'www.example.com', 'www.example.com', 
         'www.example.com', 'www.example.com', 'www.example.com']

new_links = []

def create_workers():
    for _ in range(4):
        t = threading.Thread(target=work)
        t.daemon = True
        t.start()

    for _ in range(2):
        t = threading.Thread(target=work_two)
        t.daemon = True
        t.start()

def work():
    while True:
        work = queue.get()
        #do something
        queue.task_done()

def work_two():
    while True:
        work = queue_two.get()
        #do something
        queue_two.task_done()

def create_jobs():
    for link in links:
        queue.put(link)
    queue.join()
    crawl_two()
    crawl()

def create_jobs_two():
    for link in new_links:
        queue_two.put(link)
    queue_two.join()
    crawl_two()

def crawl():
    queued_links = links
    if len(queued_links) > 0:
        create_jobs()

def crawl_two():
    queued_links = new_links
    if len(queued_links) > 0:
        create_jobs_two()

create_workers()
crawl()

1 个答案:

答案 0 :(得分:0)

这是因为你的处理在工作和工作之间似乎并不平行。

这就是:

  1. 您为工作和工作创建工作人员_two
  2. 称为抓取
  3. 调用Create_jobs - “工作”工作人员开始处理它们
  4. Create_jobs在queue.join()中等待,直到所有这些内容都完成
  5. Crawl_two被称为
  6. 调用Create_jobs_two - “work_two”工作人员开始处理它们
  7. Create_jobs_two在queue_two.join()中等待,直到所有这些都完成
  8. 调用爬网(从2开始)
  9. 基本上你永远不会进入work和work_two并行运行的情况,因为你使用queue.join()等待所有当前正在运行的任务完成。只有这样,您才能将任务分配给“其他”队列。你的工作和work_two本身并行运行,但控制结构确保工作和work_two是互斥的。如果您希望它们两者并行运行,则需要重新设计循环和队列。

    您可能还想调查使用threading.Lock()来保护您的全局new_links变量,因为我假设您将在工作线程中附加内容。这绝对没问题,但你需要一个锁来确保两个线程不会同时尝试这样做。但这与您当前的问题无关。这只能帮助您避免下一个问题。

    我当然不知道你试图在这里实现什么,但是你可以通过完全废弃全局new_links来尝试解决你的问题并避免下一个问题。如果你的工作和工作 - 如果他们需要向他们提交任务,而不是将项目放入一个全局变量然后将它们提供给主线程中的队列,那么你的工作和work_two只是为其提供了什么呢?

    或者您可以构建一个“编排”线程,该任务将任务排入工作人员,处理来自他们的响应,然后相应地对该响应进行操作,或者将其排队到其中一个队列,或者如果“准备好”则接受结果。