Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我是否可以假设线程已完成。active_count()返回1?_Python_Multithreading_Python Multithreading - Fatal编程技术网

Python 我是否可以假设线程已完成。active_count()返回1?

Python 我是否可以假设线程已完成。active_count()返回1?,python,multithreading,python-multithreading,Python,Multithreading,Python Multithreading,鉴于以下类别: 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=

鉴于以下类别:

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)
当所有线程都完成后,仍然有一个活动线程-
线程。最后一行的active_count()
会告诉我这个数字

活动线程是
——与
threading.enumerate()
一起打印

active\u count()==1
时,我是否可以假设所有线程都已完成? 或者,例如,导入的模块可以启动额外的线程,以便在
active\u count()>1
时实际完成我的线程,这也是我在run方法中使用的循环的条件。

根据
active\u count()
包括主线程,因此如果你是1,那么你很可能完成了,但是如果您的程序中有另一个新线程源,那么您可以在
active\u count()
点击1之前完成

我建议在
ScraperPool
上实现显式
join
方法,并跟踪工作线程,在需要时显式地将它们连接到主线程,而不是检查是否完成了
active_count()
调用

还记得关于GIL…

根据
active\u count()
包括主线程,因此如果你是1,那么你很可能已经完成了,但是如果你的程序中有另一个新线程源,那么你可能在
active\u count()
点击1之前就完成了

我建议在
ScraperPool
上实现显式
join
方法,并跟踪工作线程,在需要时显式地将它们连接到主线程,而不是检查是否完成了
active_count()
调用


还记得GIL…

活动计数()达到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()

您可以假设当
active\u 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()

缺少
类TestScraper():
行?为了简单起见,我只发布了部分代码。我现在在完整的脚本中添加了一个pastebin链接。您发布的代码需要是最小的、完整的和可验证的(),这似乎错过了导入和定义链接。我希望我的文章现在达到了标准。导入的模块可以启动后台线程,所以不,你不能等到线程计数为1。<代码>类TestSurror():< /Cord>行没有。为了保持简单,我只发布了部分代码。我现在在完整的脚本中添加了一个pastebin链接。您发布的代码需要是最小的、完整的和可验证的(),这似乎错过了导入和定义链接。我希望我的文章现在达到标准。导入的模块可以启动后台线程,所以不,你不能等到线程数是1。如果你在1,你就完成了。但是,如果任何其他模块创建了一个线程,您将永远无法得到1。这就是OP的要求。如果你是1,你就完蛋了。但是,如果任何其他模块创建了一个线程,您将永远无法得到1。这就是OP的要求。我最初是在整数
scraperpool.ActiveWorkersCount
中跟踪活动的scraper,当一个worker启动/停止时,它会递增/递减。然后我遇到了
threading.active\u count()
,并尝试使用该方法。我最初的方法就是你所说的“管理你的线程”吗?我想我还不太了解
线程。join()
,不过,我得研究一下。你能举个例子吗?我会发布一些代码,但看起来你想要的已经在
multiprocessing.pool.ThreadPool
中实现了。您可能想检查一下,“加入”只是意味着等待线程完成。一些线程对象是在后台清理的,所以这样做有一个次要的技术原因,但主要是为了确保线程完成其工作。我最初是在整数
scraperpool.ActiveWorkersCount
中跟踪活动的scraper,当工作人员启动/停止时,该值会增加/减少。然后我遇到了
threading.active\u count()
,并尝试使用该方法。我最初的方法就是你所说的“管理你的线程”吗?我想我还不太了解
线程。join()
,不过,我得研究一下。你能举个例子吗?我会发布一些代码,但看起来你想要的已经在
multiprocessing.pool.ThreadPool
中实现了。您可能想检查一下,“加入”只是意味着等待线程完成。一些线程对象是在封面下清理的,所以这样做有一个次要的技术原因,但大多数情况下,这只是确保线程完成其工作的方式。