Python 3限制活动线程数(完成的线程不退出)

时间:2018-02-08 10:52:17

标签: python multithreading python-3.x class python-3.6

我想限制活动线程的数量。我所看到的是,一个完成的线程保持活着并且不会自行退出,因此活动线程的数量会一直增长,直到出现错误。

以下代码一次只启动8个线程,但即使完成它们也会保持活动状态。所以数字不断增长:

class ThreadEx(threading.Thread):
    __thread_limiter = None
    __max_threads = 2

    @classmethod
    def max_threads(cls, thread_max):
        ThreadEx.__max_threads = thread_max
        ThreadEx.__thread_limiter = threading.BoundedSemaphore(value=ThreadEx.__max_threads)

    def __init__(self, target=None, args:tuple=()):
        super().__init__(target=target, args=args)
        if not ThreadEx.__thread_limiter:
            ThreadEx.__thread_limiter = threading.BoundedSemaphore(value=ThreadEx.__max_threads)

    def run(self):
        ThreadEx.__thread_limiter.acquire()
        try:
            #success = self._target(*self._args)
            #if success: return True
            super().run()
        except:
            pass
        finally:
            ThreadEx.__thread_limiter.release()


def call_me(test1, test2):
    print(test1 + test2)
    time.sleep(1)


ThreadEx.max_threads(8)

for i in range(0, 99):
    t = ThreadEx(target=call_me, args=("Thread count: ", str(threading.active_count())))
    t.start()

由于for循环,线程数保持增长到99。 我知道一个线程已完成其工作,因为 call_me 已被执行并且 threading.active_count()已被打印。

有人知道我是如何确定的,完成的线程不能保持活着吗?

2 个答案:

答案 0 :(得分:0)

这可能是一个愚蠢的答案,但对我来说,你看起来正试图重新发明ThreadPool

from multiprocessing.pool import ThreadPool
from time import sleep

p = ThreadPool(8)

def call_me(test1):
    print(test1)
    sleep(1)

for i in range(0, 99):
    p.apply_async(call_me, args=(i,))

p.close()
p.join()

这将确保在任何时间点只有8个并发线程正在运行您的函数。如果您想要更高的性能,可以从多处理中导入Pool并使用它。接口完全相同,但您的池现在将是子进程而不是线程,这通常会提高性能,因为GIL不会妨碍。

答案 1 :(得分:0)

我根据Hannu的帮助改变了班级。

我发布它以供参考,也许对于遇到这篇文章的其他人有用:

import threading
from multiprocessing.pool import ThreadPool
import time

    class MultiThread():
    __thread_pool = None

    @classmethod
    def begin(cls, max_threads):
        MultiThread.__thread_pool = ThreadPool(max_threads)

    @classmethod
    def end(cls):
        MultiThread.__thread_pool.close()
        MultiThread.__thread_pool.join()

    def __init__(self, target=None, args:tuple=()):
        self.__target = target
        self.__args = args

    def run(self):
        try:
            result = MultiThread.__thread_pool.apply_async(self.__target, args=self.__args)
            return result.get()
        except:
            pass


def call_me(test1, test2):
    print(test1 + test2)
    time.sleep(1)
    return 0


MultiThread.begin(8)
for i in range(0, 99):
    t = MultiThread(target=call_me, args=("Thread count: ", str(threading.active_count())))
    t.run()
MultiThread.end()

在任何给定时间,线程的最大值为8,由 begin 方法确定。 而且 run 方法返回传递函数的结果,如果返回的话。

希望有所帮助。