ホームページ  >  記事  >  バックエンド開発  >  Python スレッド プールについてさらに理解する

Python スレッド プールについてさらに理解する

高洛峰
高洛峰オリジナル
2016-10-19 15:13:131255ブラウズ

スレッドプールの概念とは何ですか?

オブジェクト指向プログラミングでは、オブジェクトの作成にはメモリ リソースやその他のリソースを取得する必要があるため、オブジェクトの作成と破棄には非常に時間がかかります。これは特に Java に当てはまります。Java では、オブジェクトが破棄された後にガベージ コレクションできるように、仮想マシンはすべてのオブジェクトを追跡しようとします。したがって、サービス プログラムの効率を向上させる 1 つの方法は、作成および破棄されるオブジェクトの数、特にリソースを大量に消費するオブジェクトの作成および破棄の数をできる限り減らすことです。既存のオブジェクトをどのように使用してサービスを提供するかは、解決する必要がある重要な問題です。実際、これがいくつかの「プールされたリソース」テクノロジーの出現の理由です。

スレッドプールとは多数のスレッドを格納する単位であり、それに対応するタスクキューもあると理解しています。実際の実行プロセス全体は、スレッド プール内の限られたスレッドを使用して、タスク キュー内のタスクを完了します。この利点は、タスクごとにスレッドを作成する必要がないことです。100 番目のタスクを実行するために 100 番目のスレッドを作成すると、作業を終了した前のスレッドが 50 個存在する可能性があるためです。したがって、タスクを実行するためにスレッドが再利用され、システム リソースのオーバーヘッドが削減されます。

不適切な比喩としては、1 階から 2 階に移動する必要があるコンピューターのメインフレームが 100 台あり、移動を手伝ってもらうために 100 人を呼ぶ必要はありません。10 人か 20 人を呼ぶだけで済みます。全員が 10 個または 5 個を割り当てます。あるいは、より速く移動した人がより多く移動して、完了が不明であることを確認します。 (この比喩は...)

とにかく、スレッドプールの概念は大体理解できました。では、Python を使用して実装するにはどうすればよいでしょうか?

コードは次のとおりです

# !/usr/bin/env python
# -*- coding:utf-8 -*-
# ref_blog:http://www.open-open.com/home/space-5679-do-blog-id-3247.html
import Queue
import threading
import time
class WorkManager(object):
    def __init__(self, work_num=1000,thread_num=2):
        self.work_queue = Queue.Queue()
        self.threads = []
        self.__init_work_queue(work_num)
        self.__init_thread_pool(thread_num)
    """
        初始化线程
    """
    def __init_thread_pool(self,thread_num):
        for i in range(thread_num):
            self.threads.append(Work(self.work_queue))
    """
        初始化工作队列
    """
    def __init_work_queue(self, jobs_num):
        for i in range(jobs_num):
            self.add_job(do_job, i)
    """
        添加一项工作入队
    """
    def add_job(self, func, *args):
        self.work_queue.put((func, list(args)))#任务入队,Queue内部实现了同步机制
    """
        检查剩余队列任务
    """
    def check_queue(self):
        return self.work_queue.qsize()
    """
        等待所有线程运行完毕
    """ 
    def wait_allcomplete(self):
        for item in self.threads:
            if item.isAlive():item.join()
class Work(threading.Thread):
    def __init__(self, work_queue):
        threading.Thread.__init__(self)
        self.work_queue = work_queue
        self.start()
    def run(self):
        #死循环,从而让创建的线程在一定条件下关闭退出
        while True:
            try:
                do, args = self.work_queue.get(block=False)#任务异步出队,Queue内部实现了同步机制
                do(args)
                self.work_queue.task_done()#通知系统任务完成
            except Exception,e:
                print str(e)
                break
#具体要做的任务
def do_job(args):
    print args
    time.sleep(0.1)#模拟处理时间
    print threading.current_thread(), list(args)
if __name__ == '__main__':
    start = time.time()
    work_manager =  WorkManager(10, 2)#或者work_manager =  WorkManager(10000, 20)
    work_manager.wait_allcomplete()
    end = time.time()
    print "cost all time: %s" % (end-start)

このコードは明確で理解しやすいです。

コード全体には WorkManager と Work の 2 つのクラスしかありません。前者は名前が示すとおりマネージャーであり、スレッド プールとタスク キューを管理します。一方、後者は特定のスレッドです。

その全体の動作ロジックは、指定された量のタスクとスレッド数を WorkManager に割り当て、各スレッドがタスク キューからタスクを取得して、キューにタスクがなくなるまで実行します。ここでも Queue の内部同期メカニズムが使用されています (同期メカニズムはまだ研究されていません)。

このようなスレッド プールの役割を要約すると、私の本来の目的では、これは実際には決して利用できません。Web ページ上のスレッドの開始と停止を制御する必要があり、このスレッド プールは目的でのみ使用されるようです。同時完了タスク。ただし、スレッドの制御には効果がありませんが、タスクを並行して実行する役割は非常に優れていると思います。Web ページのクローリングに使用される可能性があります。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。