2016-07-18 39 views
1

我想實現一個Consumer Producer實現。我還沒有實現消費者,因爲我與製作人有問題。目的是在互聯網上下載一些文件。線程是在自定義對象的方法內部啓動的。線程是子類化threading.Thread的對象。下面是代碼來自隊列中生產者消費者的另一個類的線程

downloader_thread.py

from threading import Thread 

import time 


class Downloader(Thread): 
    def __init__(self, queue, out_queue): 
     super(Downloader, self).__init__() 
     self.queue = queue 
     self.out_queue = out_queue 

    def run(self): 
     while True: 
      page = self.queue.get() 
      if page: 
       print "Simulating download" 
       print "Downloading page ", page 
       time.sleep(3) 
       self.out_queue.put(page) 

      self.queue.task_done() 

main_class.py

from Queue import Queue 

from downloader_thread import Downloader 


class Main(object): 
    def __init__(self): 
     self.queue = Queue(0) 
     self.out_queue = Queue(0) 
     self.threads = [] 
     self.max_threads = 5 

    def download(self): 
     page = 1 
     for i in range(self.max_threads): 
      download_thread = Downloader(self.queue, self.out_queue) 
      download_thread.setDaemon(True) 
      download_thread.start() 
      self.threads.append(download_thread) 

     while page < 100: 
      self.queue.put(page) 
      page += 1 

     self.queue.join() 

     for thread in self.threads: 
      thread.join() 


if __name__ == "__main__": 

    main = Main() 
    main.download() 
    while not main.out_queue.empty(): 
     print main.out_queue.get() 

問題是,啓動線程通常他們的所有五個,他們執行的是run方法,但不停止,所以一直沒有執行。我還挺新的線程和併發編程,所以請溫柔:)

的一點是要有一個消費者線程處理的代碼,同時一部分,而不是有這一點的同時,在「主要」:一部分代碼

回答

1

你的線程永遠不會終止,因爲它們有一個無限循環的run()方法。在你download()方法你join()那些線程:

 for thread in self.threads: 
      thread.join() 

等程序被阻止。只要刪除連接,就好像你的意思是讓這些線程在程序的一生中持續存在。

+0

謝謝你的快速回復。終止線程的工作由queue.join()和queue.task_done()正確的隊列來處理? – Apostolos

+0

不,線程永遠不會在當前實現的程序生命週期中終止。它們允許終止python程序,因爲它們是守護線程。當'queue'耗盡時,它們在'page = self.queue.get()'中被阻塞。你用'queue.task_done()'做了正確的選擇,你可以用'queue.join()'來等待隊列中所有的項目被獲取和處理。 –

+0

當下載返回當前實現時,有沒有辦法結束線程?我猜不正確?有沒有辦法強制他們停止?我聽說強制停止線程是正確的不是最佳做法嗎? – Apostolos