2017-08-14 4 views
0

私は異なるタスク用に2つのキューを持っていますが、最初のクロールではリスト内のリンクをクロールし始め、さらにキューへのリンクを生成し、キュー2上の別のタスクへの新しいリンクを生成します私のプログラムは動作していますが、問題は次のとおりです。キュー2のワーカーが実行を開始すると、キュー1からワーカーが停止しますが、基本的に並行して実行されていません。どうすればそれらを並行して走らせることができますか?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

これは、処理が仕事と仕事の2つの間で平行ではないようだからです。

これは何が起こるかです:

  1. あなたは仕事のために労働者を作成し、
  2. クロールが
  3. CREATE_JOBSが呼ばれると呼ばれるwork_two - "仕事" 労働者
  4. CREATE_JOBSがするまでqueue.join()で待機して処理を開始すべてが完了しました
  5. Crawl_twoは
  6. と呼ばれています。Create_jobs_twoは - "work_ 2」労働者は基本的にどこの仕事とwork_twoは希望状況に入ることはありません彼らに
  7. Create_jobs_twoそれらのすべてがクロールが(再び2から開始)と呼ばれている
  8. を完了するまでqueue_two.join()で待機

の処理を開始します並行して実行するには、queue.join()を使用して、現在実行中のすべてのタスクが終了するまで待ちます。その後、タスクを「その他の」キューに割り当てます。あなたの仕事とwork_twoは自分自身の中で並行して実行されますが、コントロール構造はworkとwork_twoが互いに排他的であることを保証します。ループとキューの両方を並行して実行したい場合は、ループとキューを再設計する必要があります。

グローバルnew_links変数を保護するためにthreading.Lock()の使用を調べたいと思うかもしれません。ワーカースレッドで変数を追加することを前提としています。これは絶対に問題ありませんが、2つのスレッドがこれを同時に実行しようとしていないことを保証するにはロックが必要です。しかし、これはあなたの現在の問題とは関係ありません。これは、次の問題を回避するのに役立ちます。

もちろん、あなたがここで達成しようとしていることはわかりませんが、問題を解決し、グローバルnew_linksを完全に破棄して次の問題を回避してみてください。あなたの仕事とwork_twoは、項目をグローバル変数に入れてメインスレッドのキューに入れずに、タスクをサブミットする必要がある場合、他のワーカーのキューにフィードしただけですか?

または、タスクをワーカーにキューイングし、その応答を処理し、それに応じてその応答を処理する「オーケストレーション」スレッドを作成して、キューの1つにキューイングしたり、 "

関連する問題