Select Language

AI Technology Community

8.2、Python threadモジュールの使用方法の詳細

このパッケージはPython 2では正常に使用できる状態ですが、Python 3では廃止予定の状態にあります。まだ使用できますが、パッケージ名は_threadに変更されています。

threadパッケージを使用するには、まずこのパッケージをインポートする必要があります。Python 2では、以下の文を使用してインポートします:

import thread

一方、Python 3では、パッケージ名がthreadから_threadに変更されたため、以下の文を使用してインポートする必要があります:

import _thread


一貫性を保つために、まず現在使用しているのがPython 2かPython 3かを判断し、それに応じて異なるパッケージをインポートし、Python 3ではパッケージをthreadという名前で再命名することができます。コードは以下の通りです:

import sys
if sys.version_info.major == 2:   # Python 2
    import thread
else:                             # Python 3
    import _thread as thread

スレッドの起動

threadパッケージでは、スレッドのエントリーポイントとして関数を定義する必要があります。以下の関数を作成します。この関数は1秒ごとに1行のメッセージを出力し、10回出力した後に終了します。コードは以下の通りです:

def thread_entry(id):
    cnt = 0
    while cnt < 10:          # ループ回数が足りない
        print('Thread:(%d) Time:%s' % (id, time.ctime()))
        time.sleep(1)               # 1秒待機
        cnt = cnt + 1


また、特定のスレッドを起動するには、以下のメソッドを使用できます:

start_new_thread(function, args[, kwargs])

このメソッドの最初のパラメーターfunctionは、実行する関数を表します。上で定義した関数名のようなもので、この関数はスレッドのエントリー関数として使用されます。argsとkwargsはその関数のパラメーターです。argsは必須で、タプル型です。kwargsはオプションで、辞書型です。

ここではargsのみを使用し、パラメーターは1つだけです。コードは以下の通りです:

def start_threads():
    t1 = thread.start_new_thread(thread_entry, (1,))    # スレッド1を起動
    t2 = thread.start_new_thread(thread_entry, (2,))    # スレッド2を起動
    time.sleep(12)      # 待機


start_threads()関数は2つのスレッドを起動します。各スレッドはthread_entry()をエントリー関数として使用します。以下は完全なコードです。

import time, sys                      # timeとsysモジュールをインポート
if sys.version_info.major == 2:       # 現在使用しているのがPython 2インタープリターの場合
     import thread
else:                                 # 現在使用しているのがPython 3インタープリターの場合
     import _thread as thread
def thread_entry(id):                 # エントリー関数を定義
    cnt = 0
    while cnt < 10:                      # 10回ループし、毎回1行を出力
        print('Thread:(%d) Time:%s' % (id, time.ctime()))
        time.sleep(1)
        cnt = cnt + 1
def start_threads():                  # スレッドを起動
    t1 = thread.start_new_thread(thread_entry, (1,))
    t2 = thread.start_new_thread(thread_entry, (2,))
    time.sleep(12)
if __name__=='__main__':              # スクリプトを実行
    start_threads()


このスクリプトを実行すると、以下のように出力されます:

$ python3 createThreadDemo1.py
Thread:(1) Time:Fri May 10 06:00:29 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:29 2019                # スレッド2の9行目の出力
Thread:(2) Time:Fri May 10 06:00:30 2019                # スレッド2の9行目の出力
Thread:(1) Time:Fri May 10 06:00:30 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:31 2019
Thread:(1) Time:Fri May 10 06:00:31 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:32 2019                # スレッド2の9行目の出力
Thread:(1) Time:Fri May 10 06:00:32 2019
Thread:(2) Time:Fri May 10 06:00:33 2019                # スレッド2の9行目の出力
Thread:(1) Time:Fri May 10 06:00:33 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:34 2019
Thread:(1) Time:Fri May 10 06:00:34 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:35 2019                # スレッド2の9行目の出力
Thread:(1) Time:Fri May 10 06:00:35 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:36 2019
Thread:(1) Time:Fri May 10 06:00:36 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:37 2019                # スレッド2の9行目の出力
Thread:(1) Time:Fri May 10 06:00:37 2019                # スレッド1の9行目の出力
Thread:(2) Time:Fri May 10 06:00:38 2019
Thread:(1) Time:Fri May 10 06:00:38 2019

Thread1とThread2が交互に実行されていることがわかります。あるスレッドが完了してから別のスレッドが実行されるわけではありません。これら2つのスレッドの実行順序には特定の規則がなく、ある程度のランダム性があります。したがって、2つのスレッドは並行して実行されていると見なすことができます。

スレッドの終了

上でエントリー関数の定義方法とスレッドの起動方法を説明しました。では、スレッドはどのように終了するのでしょうか?以下のような終了方法があります:

  • エントリー関数が実行を完了する。

  • スレッドが未処理の例外をスローする。

  • スレッド内部で_thread.exit_thread()を呼び出して終了する。


前の例では、エントリー関数が実行を完了することでスレッドを終了しました。以下の例では、_thread.exit_thread()を使用してスレッドを終了する方法を示します。この例では、エントリー関数はグローバル変数を使用して終了するかどうかを判断します。このグローバル変数はメインスレッドによって制御されます。完全なコードは以下の通りです:

import time, sys
if sys.version_info.major == 2:      # Python 2
    import thread
else:                                # Python 3
    import _thread as thread
g_continue = True                    # 継続実行のフラグ
def thread_entry(id):                # スレッドのエントリー関数
    global g_continue
    while True:
        if not g_continue:           # フ
post
  • 10

    item of content
プロセスはリソースを分配する単位であり、スレッドはオペレーティングシステムがスケジューリングできる最小の単位です。
通常、プロセスには少なくとも1つのスレッドが含まれ、複数のスレッドがある場合はその中にメインスレッドが含まれます。同じプロセス内のすべてのスレッドはシステムリソースを共有しますが、それぞれが独立したスタック、レジスタ環境、およびローカルストレージを持っています。
マルチスレッドの利点は、複数のタスクを同時に実行できることです。システムに複数の計算ユニットがある場合、複数のスレッドはそれぞれの計算ユニットで並行して動作することができ、これによりシステムの処理効率が大幅に向上します。
多くの場合、プロセスはスレッドよりも大きい単位であり、通常1つのプロセスは複数のスレッドを含むことができます。プロセスの隔離効果はスレッドよりも優れているため、マルチプロセスを使用するとマルチスレッドよりも安全です。ただし、マルチプロセスの欠点はマルチスレッドよりもスケジューリングが重く、効率が低いことです。