pythonにおいて
複数回数、同じタスクを処理するスレッドを
メインの関数で作成しスタートしてから、
ランダムなタイミングで停止させるときに、
そのスレッド内に記述したタスクを
何回完了したのか知りたいときには、
まず、メインのクラス内に
タスク用のスレッドを保持し、(thread A)
そのタスク用のスレッドを停止させるスレッドを保持し、(thread B)
この2つのスレッドA,Bの間では 停止させるタイミングを知るための
threading.Eventのインスタンスを共有させると思うのですが、
メインのクラスがスレッドAのタスクの完了回数を知るためには
別のリソース用のクラスのインスタンスを
メインのクラスと、スレッドAの間で共有させるものなのでしょうか?
↓
そのアプローチは適切で、以下のように整理できます。
1. **メインのクラス**
- タスク用スレッド(スレッドA)と停止制御スレッド(スレッドB)を管理する。
- `threading.Event`を使用してスレッド間の停止タイミングを制御する。
- タスクの完了回数を追跡するためにリソース用のクラスをスレッドAと共有する。
2. **スレッドA**
- タスクを繰り返し実行し、完了するごとに共有リソースに完了回数を記録する。
- `threading.Event`の状態を監視し、停止条件を確認する。
3. **リソース用のクラス**
- スレッド間で共有され、スレッドAがタスクの完了回数を記録し、
メインスレッドがその値を読み取る。
### 実装例
以下のコードで説明します:
```python
import threading
import time
import random
# タスクの完了回数を管理するリソースクラス
class TaskCounter:
def __init__(self):
self.count = 0
self.lock = threading.Lock()
def increment(self):
# スレッドセーフにするためロックを使用
with self.lock:
self.count += 1
def get_count(self):
with self.lock:
return self.count
# タスク用のスレッドA
def task_thread(stop_event, task_counter):
# stop_event がセットされるまでループ
while not stop_event.is_set():
# タスクを実行 (ここではダミーの処理)
time.sleep(random.uniform(0.1, 0.5)) # タスクの実行時間
task_counter.increment() # 完了回数を増やす
print("Task completed")
# 停止制御用のスレッドB
def control_thread(stop_event, duration):
time.sleep(duration) # 指定時間後に停止
stop_event.set()
print("Stop event set")
# メインスレッド
def main():
stop_event = threading.Event() # 停止フラグ
task_counter = TaskCounter() # タスク完了回数を管理するインスタンス
# スレッドAを作成してスタート
thread_a
= threading.Thread(
target=task_thread,
args=(stop_event, task_counter))
thread_a.start()
# スレッドBを作成してスタート
duration = 5 # スレッドAを5秒後に停止
thread_b
= threading.Thread(target=control_thread,
args=(stop_event, duration))
thread_b.start()
# スレッドA, Bの終了を待機
thread_a.join()
thread_b.join()
# タスク完了回数を表示
print(f"Total tasks completed:
{task_counter.get_count()}")
if __name__ == "__main__":
main()
```
### 説明
1. **共有リソースクラス (TaskCounter)**
- `increment`メソッドでタスクの完了回数を増加。
- `get_count`メソッドで完了回数を取得。
- ロックを使ってスレッドセーフに管理。
2. **スレッド間通信 (threading.Event)**
- `stop_event`を使用してスレッドAのループを終了。
- スレッドBが指定時間後に`stop_event.set()`を呼び、
スレッドAに停止を通知。
3. **タスク完了回数の追跡**
- タスク完了ごとに`task_counter.increment()`を呼び出して
完了回数を記録。
- メインスレッドが`task_counter.get_count()`を呼び出して
結果を表示。
これでスレッド間の同期が安全かつ簡潔に実現できます。
コメント
コメントを投稿