I.はじめに
Python のマルチスレッドおよびマルチプロセス プログラミングにおいて、join()
とEvent
はどちらもスレッドやプロセス間の同期関係を制御するために使用されるツールであり、機能は似ていますが、いくつかの違いがあります。
2. コンセプト
1.結合()
join()
メソッドは、スレッドまたはプロセスの実行が完了するまで、現在呼び出しているスレッドまたはプロセスをブロックしてから、後続のコードの実行を続行する、スレッドまたはプロセス インスタンスのメソッドです。join()
メソッドは、別のスレッドまたはプロセスの完了を待つためによく使用されます。親プロセスでは、join()
親プロセスのコードの実行を続行する前に、すべての子プロセスが完了するまで待機するために使用できます。
2. イベント
Event
これはスレッドまたはプロセスの同期メカニズムであり、主にスレッド間の通信に使用されます。A はEvent
内部フラグを表し、設定またはクリアできます。set()
イベントフラグを設定するメソッドと、wait()
フラグが設定されるのを待つメソッドを使用できます。さらに、clear()
メソッドを使用してフラグをクリアすることもできます。
3. 違い
join()
スレッドまたはプロセスに属するインスタンス メソッドは、現在のスレッドまたはプロセスでのみ使用でき、Event
スレッドまたはプロセス間で共有できます。join()
この機能は、後続のコードの実行を継続するためにスレッドまたはプロセスの実行が完了するのを待機することであり、Event
ローカル待機を実現するためにスレッド間の同期と通信を行うことです。
一般に、join()はスレッドやプロセス間の実行順序を制御するのに適しており、Eventはスレッド間の同期や通信を部分的にのみ実現するのに適しています。
4. サンプルコード
スレッドを例に挙げますが、プロセスの実装も同様です。
1. join() を使用する
スレッドの実行が完了するまで待ってから、次のステップを実行します
# -*- coding:utf-8 -*-
import time
import threading
def run(n, event):
for i in range(1000):
print(i, end=' ')
# event.set()
while n > 0:
print('Threading:', n)
n -= 1
time.sleep(1)
event = threading.Event()
if __name__ == '__main__':
print('start threading.')
t = threading.Thread(target=run, args=(5, event))
t.start()
t.join()
# event.wait()
print('end threading...')
実行結果:プログラムがすべてのコードを順番に実行していることがわかります。
2. イベントを使用する
次のコードを実行する前に、スレッド内のコードの一部が実行されるのを待ちます。
# -*- coding:utf-8 -*-
import time
import threading
def run(n, event):
for i in range(1000):
print(i, end=' ')
event.set()
while n > 0:
print('Threading:', n)
n -= 1
time.sleep(1)
event = threading.Event()
if __name__ == '__main__':
print('start threading.')
t = threading.Thread(target=run, args=(5, event))
t.start()
# t.join()
event.wait()
print('end threading.')
end threading
実行効果: for ループ コードの実行が完了するのを待った後でコードが実行されることがわかります。イベントは待機の一部にすぎないことを説明します。
3. イベントを利用せずに参加する
コード
# -*- coding:utf-8 -*-
import time
import threading
def run(n, event):
for i in range(1000):
print(i, end=' ')
# event.set()
while n > 0:
print('Threading:', n)
n -= 1
time.sleep(1)
event = threading.Event()
if __name__ == '__main__':
print('start threading.')
t = threading.Thread(target=run, args=(5, event))
t.start()
print('end threading.')
end threading
実行効果: for ループの前に実行され、for ループ コードの実行を待機しないことがわかります。
Windows のプロセス スレッド数を確認するためのいくつかの方法を添付します。
方法 1
# 获取 WMI 对象
wmi = win32com.client.GetObject("winmgmts:")
# 查询进程信息
process_query = "SELECT * FROM Win32_Process"
process_result = wmi.ExecQuery(process_query)
process_count = len(process_result)
# 查询线程信息
thread_query = "SELECT * FROM Win32_Thread"
thread_result = wmi.ExecQuery(thread_query)
thread_count = len(thread_result)
print("系统进程数量:", process_count)
print("系统线程数量:", thread_count)
方法 2
import psutil
# 获取进程数量
process_count = len(psutil.pids())
print("进程数量:", process_count)
# 获取线程数量
thread_count = 0
for proc in psutil.process_iter(['pid', 'name']):
try:
pinfo = proc.as_dict(attrs=['pid', 'name', 'num_threads'])
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
else:
thread_count += pinfo['num_threads']
print("线程数量:", thread_count)
方法 3
import multiprocessing
import threading
print(f"Process {
multiprocessing.current_process().pid}: {
threading.active_count()} threads")
print(f"Process {
threading.current_thread()}: {
threading.active_count()} threads")
print(f"Total threads: {
threading.active_count()}")
print(f"Total processes: {
len(multiprocessing.active_children())}")
5. まとめ
- メインスレッドまたはメインプロセスの実行中は、後続の操作の実行を続ける前に、サブスレッドまたはサブプロセスが特定のタスクを完了するまで待つ必要があります。join() メソッドが使用されていない場合、サブスレッドまたはサブプロセスがタスクを完了する前にメインスレッドまたはメインプロセスが終了し、プログラム例外または不正な結果が発生する可能性があります。
- join() と Event はどちらもマルチスレッドおよびマルチプロセス プログラミングにおいて非常に重要な同期ツールであり、プログラムの信頼性と効率性を高めることができます。プログラムが実行を続行する前に他のスレッドまたはプロセスが完了するのを待つ必要がある場合は、join() メソッドを使用できます。プログラムが複数のスレッドまたはプロセスと調整して通信する必要がある場合は、Event を使用できます。
もちろん、同時に、 join() メソッドを使用するときは、デッドロックや競合状態を避けるために、スレッドまたはプロセス間の同期と相互排他の問題を考慮する必要があることに注意してください。