メインコンテンツへスキップ

threading.Threadについて

🧵はじめに:threading.Threadとは何か?

Pythonのthreading.Threadは、複数の処理を同時に進めたいときに使われる、並行処理のための仕組みです。例えば「UIを表示しながらデータを定期取得したい」といった場面で活躍します。

Pythonは「GIL(Global Interpreter Lock)」という制約のために、マルチコアCPUをフル活用する並列処理には制限がありますが、I/O待ちのある処理(ファイル読み書き、ネット通信、スリープなど)においては、threadingによるスレッド並行処理はとても有効です。


🧷基本の使い方:Threadの作り方と実行

🧬スレッドを定義して実行する方法は2通り

✅ 方法1:関数をそのままスレッドで実行する

import threading

def worker():
    print("スレッドで動いています")

t = threading.Thread(target=worker)
t.start()
t.join()

✅ 方法2:Threadクラスを継承して自分でクラスを作る

import threading

class MyThread(threading.Thread):
    def run(self):
        print("runメソッドがスレッドで呼ばれます")

t = MyThread()
t.start()
t.join()

どちらも正しい方法ですが、処理が単純なら関数ベース(target=)状態を持たせたり複雑なロジックを入れたいならクラス継承型がオススメです。


🧪重要なメソッドたち

🔸 start()

スレッドを開始します。内部でrun()が呼ばれます。

🔸 run()

start()から自動的に呼ばれるメソッド。継承型でオーバーライドします。

🔸 join(timeout=None)

メインスレッドが、対象スレッドの終了を待つために使います。引数なしだと終了までずっと待ちます。

joinを使わないと、メインスレッドが先に終わってスレッド処理が途中で終了する可能性があります。


🔁よくある用途:ループ+スリープで定期実行

import threading
import time

def periodic_task():
    while True:
        print("定期的な処理")
        time.sleep(1)

t = threading.Thread(target=periodic_task, daemon=True)
t.start()

time.sleep(5)
print("メインスレッド終了")

daemon=Trueにしておくと、メインスレッド終了時にスレッドも強制終了されます。バックグラウンドで動く常駐処理などに便利です。


🧯注意点:threadingの落とし穴

🔥 GILによる制限

  • PythonはGILにより、複数スレッドでもCPU処理は基本的に1つずつしか実行されません。

  • 計算集約型タスクにはmultiprocessingの方が向いています。

🔥 スレッドの安全性

  • 複数スレッドから同じ変数にアクセスするときは注意が必要です。

  • threading.Lock()などの同期機構で保護しないと**競合(race condition)**が起きます。


🛠️便利な補助機能たち

🔐 Lock(排他制御)

lock = threading.Lock()

def safe_task():
    with lock:
        # このブロックは同時に1つのスレッドしか入れない
        pass

📦 スレッド間でデータをやりとり:queue.Queue

スレッド間通信にはqueueを使うと安全です(ロック内蔵)。

import queue
q = queue.Queue()
q.put(100)
val = q.get()

🔚まとめ:threading.Threadを使いこなそう

  • threading.Threadは、Pythonでの軽量な並行処理の基本手段

  • I/O処理やループ処理を非同期に進めるのにとても便利

  • GILの存在に注意しつつ、LockやQueueと組み合わせて使うのが安全なやり方