2016-11-23 21 views
1

考慮下面的類:我可以認爲我的線程在threading.active_count()返回1時完成嗎?

from abc import ABCMeta, abstractmethod 
from time import sleep 
import threading 
from threading import active_count, Thread 

class ScraperPool(metaclass=ABCMeta): 
    Queue = [] 
    ResultList = [] 

    def __init__(self, Queue, MaxNumWorkers=0, ItemsPerWorker=50): 
     # Initialize attributes 
     self.MaxNumWorkers = MaxNumWorkers 
     self.ItemsPerWorker = ItemsPerWorker 
     self.Queue = Queue # For testing purposes. 

    def initWorkerPool(self, PrintIDs=True): 
     for w in range(self.NumWorkers()): 
      Thread(target=self.worker, args=(w + 1, PrintIDs,)).start() 
      sleep(1) # Explicitly wait one second for this worker to start. 

    def run(self): 
     self.initWorkerPool() 

     # Wait until all workers (i.e. threads) are done. 
     while active_count() > 1: 
      print("Active threads: " + str(active_count())) 
      sleep(5) 

     self.HandleResults() 

    def worker(self, id, printID): 
     if printID: 
      print("Starting worker " + str(id) + ".") 

     while (len(self.Queue) > 0): 
      self.scraperMethod() 

     if printID: 
      print("Worker " + str(id) + " is quiting.") 

     # Todo Kill is this Thread. 

     return 

    def NumWorkers(self): 
     return 1 # Simplified for testing purposes. 

    @abstractmethod 
    def scraperMethod(self): 
     pass 

class TestScraper(ScraperPool): 
    def scraperMethod(self): 
     # print("I am scraping.") 
     # print("Scraping. Threads#: " + str(active_count())) 
     temp_item = self.Queue[-1] 
     self.Queue.pop() 

     self.ResultList.append(temp_item) 

    def HandleResults(self): 
     print(self.ResultList) 

ScraperPool.register(TestScraper) 

scraper = TestScraper(Queue=["Jaap", "Piet"]) 
scraper.run() 
print(threading.active_count()) 
# print(scraper.ResultList) 

當所有線程都做了,還有一個活動線程仍然是 - threading.active_count()最後一行讓我這個數字。

活動線程爲<_MainThread(MainThread, started 12960)> - 如threading.enumerate()所印。

我可以假設我的所有線程都是在active_count() == 1時完成的嗎? 或者可以,例如,導入模塊啓動額外的線程,以便我的線程實際上完成時active_count() > 1 - 也是在運行方法中使用的循環的條件。

+0

'class TestScraper():'line is absence? – cat

+0

爲了保持簡單,我只發佈了一部分代碼。我現在添加了一個pastebin鏈接到完整的腳本。 – user2693053

+0

您發佈的代碼需要Minimal,Complete和Verifiable([mcve]),並且這似乎錯過了導入和定義 – cat

回答

2

你可以假設你的線程完成時active_count()達到1問題是,如果任何其他模塊創建一個線程,你永遠也沒有機會1.你應該明確地管理你的線程。

示例:您可以將線程放在列表中並一次加入一個線程。對您的代碼的相關更改如下:

def __init__(self, Queue, MaxNumWorkers=0, ItemsPerWorker=50): 
    # Initialize attributes 
    self.MaxNumWorkers = MaxNumWorkers 
    self.ItemsPerWorker = ItemsPerWorker 
    self.Queue = Queue # For testing purposes. 
    self.WorkerThreads = [] 

def initWorkerPool(self, PrintIDs=True): 
    for w in range(self.NumWorkers()): 
     thread = Thread(target=self.worker, args=(w + 1, PrintIDs,)) 
     self.WorkerThreads.append(thread) 
     thread.start() 
     sleep(1) # Explicitly wait one second for this worker to start. 

def run(self): 
    self.initWorkerPool() 

    # Wait until all workers (i.e. threads) are done. Waiting in order 
    # so some threads further in the list may finish first, but we 
    # will get to all of them eventually 
    while self.WorkerThreads: 
     self.WorkerThreads[0].join() 

    self.HandleResults() 
+0

我最初跟蹤的是一個整數「scraperpool.ActiveWorkersCount」中的活動刮刀,當一個工人啓動/停止時,它會增加/減少。然後我遇到'threading.active_count()'並嘗試使用該方法。 我的原始方法是什麼意思與「管理你的線程」? – user2693053

+0

他意味着你應該明確地加入他們...... – user3012759

+0

我不認爲我安靜地理解'threading.join()',但是我必須研究這一點。 你能舉個例子嗎? – user2693053

2

根據docsactive_count()包括主線程,因此,如果你在1那麼你最有可能完成的,但如果你有新的線程另一個來源在你的程序,那麼你可能以前active_count()命中1來完成。

我會建議您ScraperPool實施明確join方法和跟蹤你的工人,並明確需要的不是檢查你與active_count()調用來完成他們的時候加入到主線程。

還記得大約GIL ...

+0

它的確如此,如果你在1,就完成了。但是,如果任何其他模塊創建線程,您將永遠不會達到1.這就是OP所要求的。 – tdelaney

+0

@tdelaney這就是我所說的...... – user3012759

相關問題