2017-08-14 21 views
0

我有两个队列用于执行不同的任务,第一次抓取将开始抓取列表中的链接,然后它将生成更多链接以抓取到队列中的一个,并且还会生成到队列二上不同任务的新链接,我的程序正在运行,但问题是:当队列2的工作人员开始运行时,它会阻止工作人员排队,他们基本上没有并行运行,他们正在等待彼此完成任务。我怎样才能让它们平行运行?如何创建两个不同队列并行运行的线程? - Python

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() 

回答

0

那是因为您的处理似乎不是工作和工作二之间的平行。

这是发生了什么:

  1. 创建工作的工人和work_two
  2. 抓取叫
  3. Create_jobs被称为 - “工作” 的工人开始处理他们
  4. Create_jobs在queue.join()等待他们都已完成
  5. Crawl_two被称为
  6. Create_jobs_two被调用 - “work_两个”工人开始处理这些
  7. Create_jobs_two在queue_two.join()等待,直到所有的人都完成
  8. 抓取被称为(从2重新开始)

基本上你的情况不会进入这里工作和work_two会并行运行,因为您使用queue.join()等待所有当前正在运行的任务完成。只有这样你才能将任务分配给“其他”队列。你的工作和work_two在他们自己内部并行运行,但是控制结构确保work和work_two是相互排斥的。如果你想让它们同时运行,你需要重新设计循环和队列。

您可能还想调查使用threading.Lock()来保护您的全局变量new_links,因为我认为您将在工作线程中附加事件。这是绝对好的,但你需要一个锁来确保两个线程不会同时执行此操作。但这与你目前的问题无关。这只能帮助你避免下一个问题。

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

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