はじめに
同時に並行する処理数を制限するマルチスレッドのサンプルプログラミング
コード
import threading
import logging
# デバッグログ出力設定(どのスレッドの実行かがわかるので便利)
logging.basicConfig(level=logging.DEBUG, format="%(threadName)s: %(message)s")
# 1からmaxまで、かつmultipleの倍率のみ、値を出力する
def counter(smp=threading.Semaphore(1), result=[], index=-1, multiple=1, max=1):
with smp:
for i in range(1, max + 1):
if i % multiple == 0:
logging.debug(i)
result.append(index)
if __name__ == "__main__":
# 値のループ用
params = [
{"multiple": 1, "max": 25},
{"multiple": 2, "max": 8},
{"multiple": 3, "max": 9},
{"multiple": 4, "max": 20},
{"multiple": 5, "max": 20},
]
# セマフォ定義
smp = threading.Semaphore(3)
# 各スレッドの共有の変数で使用
result = []
# パラメータベースでのループ
for index, param in enumerate(params):
# 処理完了順がわかるようにindexを追加
param["index"] = index
# スレッドの定義(targetは仕様する関数を指定、argsは引数を順番に指定、diectを渡す場合はkwargsに指定)
trd_execute = threading.Thread(
target=counter,
args=(
smp,
result,
),
kwargs=param,
)
# 処理開始
trd_execute.start()
# スレッド全体が終了するまでブロック
for trd in threading.enumerate():
if trd is threading.currentThread():
continue
trd.join()
# 処理が終わった順番が分かる
print(result)
# 終了時の処理
print("complete")
解説
初めに配列の1~3番目の値を引数としたcounterが実行され、どれかが終わったら4番目の値を引数としたcounterが実行、その後1~4番目のどれかの処理が終わったら5番目の…という形になる
また、resultの結果を見ると、処理が終わった順番が分かる
終わりに
for で thread使わなかったり、Semaphore使わなかったりすると、違いが理解できてよいかと