Python マルチスレッド

高洛峰
高洛峰オリジナル
2016-11-23 13:59:571191ブラウズ

マルチスレッドは、複数の異なるプログラムを同時に実行することに似ています。マルチスレッドには次の利点があります:

スレッドを使用すると、長期的なプログラムのタスクをバックグラウンドで処理できます。

ユーザーインターフェイスをより魅力的にすることができ、ユーザーがボタンをクリックして特定のイベントの処理をトリガーすると、プログレスバーがポップアップして処理の進行状況を表示できます

プログラムの実行速度が高速化される可能性があります

一部の待機タスクでは、たとえば、ユーザー入力、ファイルの読み取りと書き込み、ネットワークでのデータの送受信にはスレッドの方が便利です。この場合、メモリ使用量などの貴重なリソースを解放できます。

スレッドは、実行中のプロセスとは依然として異なります。それぞれの独立したスレッドには、プログラム実行のエントリ ポイント、順次実行シーケンス、およびプログラムの終了ポイントがあります。ただし、スレッドは独立して実行できず、アプリケーション プログラム内に存在する必要があり、アプリケーション プログラムは複数のスレッドの実行制御を提供します。

各スレッドには、スレッドのコンテキストと呼ばれる独自の CPU レジスタのセットがあり、スレッドが最後に実行されたときの CPU レジスタの状態を反映します。

命令ポインタとスタック ポインタ レジスタは、スレッド コンテキストで最も重要な 2 つのレジスタであり、スレッドは常にプロセス コンテキストで実行されます。これらのアドレスは、スレッドを所有するプロセスのアドレス空間内のメモリをマークするために使用されます。

スレッドはプリエンプト (中断) できます。

他のスレッドの実行中にスレッドを保留 (スリープとも呼ばれる) することができます。これをスレッド バックオフといいます。

Python スレッドの学習を始めましょう

Python でスレッドを使用するには、スレッド オブジェクトをラップする関数またはクラスの 2 つの方法があります。

機能: スレッドモジュールの start_new_thread() 関数を呼び出して、新しいスレッドを生成します。構文は次のとおりです:

thread.start_new_thread (function, args[, kwargs])

パラメータの説明:

function - スレッド関数。

args - スレッド関数に渡されるパラメータ。タプル型である必要があります。

kwargs - オプションのパラメータ。

例:

#!/usr/bin/python

インポートスレッド

インポート時間

#スレッドの関数を定義する

def print_time(threadName, late):

count = 0

while count

time.sleep(delay)

count += 1

print "%s: %s" % ( threadName, time.ctime(time.time()) )

# スレッドを 2 つ作成します

try:

thread.start_new_thread(print_time, ("Thread-1", 2,))

thread.start_new_thread(print_time, ("Thread-2", 4,) )

以外:

print "エラー: スレッドを開始できません"

while 1:

pass

上記のプログラムを実行すると、出力結果は次のようになります:

Th読む-1: 2009 年 1 月 22 日木 15:42:17

スレッド 1: 2009 年 1 月 22 日木 15:42:19

スレッド 2: 2009 年 1 月 22 日木 15:42:19

スレッド 1: 1 月木22 15:42:21 2009

スレッド-2: 木 1 月 22 日 15:42:23 2009

スレッド 1: 木 1 月 22 日 15:42:23 2009

スレッド 1: 木 1 月 22 日 15:42: 25 2009

スレッド 2: 木 1 月 22 日 15:42:27 2009

スレッド 2: 木 1 月 22 日 15:42:31 2009

スレッド 2: 木 1 月 22 日 15:42:35 2009

スレッドの終了は通常、スレッド関数の自然な終了に依存します。スレッド関数内で thread.exit() を呼び出して、スレッドを終了するという目的を達成するために SystemExit 例外をスローすることもできます。

スレッド モジュール

Python は、スレッドとスレッドという 2 つの標準ライブラリを通じてスレッドのサポートを提供します。 thread は、低レベルのプリミティブなスレッドと単純なロックを提供します。

スレッドモジュールによって提供されるその他のメソッド:

threading.currentThread(): 現在のスレッド変数を返します。

threading.enumerate(): 実行中のスレッドを含むリストを返します。実行中とは、スレッドの開始後から終了までを指します。開始前と終了後のスレッドは除きます。

threading.activeCount(): 実行中のスレッドの数を返します。これは、len(threading.enumerate()) と同じ結果になります。

使用方法に加えて、スレッド モジュールはスレッドを処理するための Thread クラスも提供します。 Thread クラスは次のメソッドを提供します:

run(): スレッドのアクティビティを表すために使用されるメソッド。

start(): スレッドアクティビティを開始します。

join([time]): スレッドが終了するまで待ちます。これにより、スレッドの join() メソッドが異常終了 (通常どおり終了するか、未処理の例外をスロー) が呼び出されるか、またはオプションのタイムアウトが発生するまで、呼び出しスレッドがブロックされます。

isAlive(): スレッドがアクティブかどうかを返します。

getName(): スレッド名を返します。

setName(): スレッド名を設定します。

Threading モジュールを使用してスレッドを作成します

Threading モジュールを使用してスレッドを作成し、threading.Thread から直接継承し、__init__ メソッドをオーバーライドしてメソッドを実行します:

#!/usr/bin /python

Importスレッジinimport time exitflag =0

classmythread(threading.thread):#inherit the parent classthreading.thread

def __ init __(self、swretid、name、and、name、カウンター)。

Print_time (Self.name, Self.Counter, 5)

Print "Exning"+Self.name

Def Print_time (ThreadName, Delay, Delay , counter):

while counter:

if exitFlag:

thread.exit()

time.sleep(lay)

print "%s: %s " % (threadName, time.ctime(time.time ()))

counter -= 1

# Create新しいスレッド

thread1 = myThread(1, "Thread-1", 1)

thread2 = myThread(2, "Thread-2", 2)

# スレッドを開始します

thread1.start()

thread2.start()

print "Exiting Main Thread"

上記プログラムの実行結果は次のとおりです

スレッド-2の開始

メインスレッドを終了します

Thread-1: Thu Mar 21 09:10:03 2013

Thread-1: Thu Mar 21 09:10:04 2013

Thread-2: Thu Mar 21 09:10:04 2013

スレッド 1: 木 3 月 21 日 09:10:05 2013

スレッド 1: 木 3 月 21 日 09:10:06 2013

スレッド 2: 木 3 月 21 日 09: 10:06 2013

スレッド 1 : Thu Mar 21 09:10:07 2013

Thread-1 を終了します

Thread-2: Thu Mar 21 09:10:08 2013

Thread-2: Thu Mar 21 09 :10:10 2013

Thread- 2: Thu Mar 21 09:10:12 2013

Exiting Thread-2

スレッド同期

複数のスレッドが共同で特定のデータを変更すると、データの正確性を保証するために予期せぬ結果が発生する可能性があります。データを処理するには、複数のスレッドを同期する必要があります。

単純なスレッド同期は、Thread オブジェクトの Lock と Rlock を使用することで実現できます。両方のオブジェクトには、一度に 1 つのスレッドのみで操作する必要があるデータの場合、操作を Acquire メソッドと Release メソッドに配置できます。メソッド間のリリース。以下の通り:

マルチスレッドの利点は、複数のタスクを同時に実行できることです (少なくともそう感じられます)。ただし、スレッドがデータを共有する必要がある場合、データの非同期の問題が発生する可能性があります。

次の状況を考えてみましょう。リスト内のすべての要素が 0 で、スレッド「set」は後ろから前にすべての要素を 1 に変更し、スレッド「print」はリストを前から後ろに読み取って印刷する責任があります。

その後、おそらくスレッド「set」が変更を開始すると、スレッド「print」がリストを出力し、出力は半分が 0 で半分が 1 になります。これがデータの非同期です。この状況を回避するために、ロックの概念が導入されました。

ロックには、ロックとロック解除の 2 つの状態があります。 「set」などのスレッドが共有データにアクセスする場合は、まずロックを取得する必要があります。「print」などの別のスレッドがすでにロックを取得している場合は、スレッド「set」を一時停止させます。これは同期ブロックです。スレッド「 Print 」まで アクセスが完了してロックが解除された後、スレッド「set」を続行させます。

このような処理を行うと、リストを印刷する際にオール0かオール1のどちらかが出力されるようになり、半分0と半分1という恥ずかしい光景はなくなりました。

例:

#!/usr/bin/python

インポートスレッド

インポート時間

classmythread(threading.thread):def __init __(self、threadid、name、counter):

threading.thread .__ init __(self)

self.threadid = self.name self.name U Self.Counter = Country

DEF RUN (Self):

Print "Starting"+Self.name

#获

、True

#optional TimeOUT パラメータの取得に成功、満たされていない場合は常にブロックされますin ロックが取得されるまで

# それ以外の場合はタイムアウト後に False を返します

threadLock.acquire()

threadLock.release()

def print_time(threadName, 遅延, カウンタ):

while counter:

time.sleep(遅延)

print "%s: %s" % (threadName, time.ctime(time.time()))

counter -= 1

threadLock = threading.Lock()

thread = []

# 新しいスレッドを作成します

thread1 = myThread(1, "Thread-1", 1)

thread2 = myThread( 2, "Thread-2", 2)

#新しいスレッドを開始します

thread1.start()

thread2.start()

# スレッドをスレッドリストに追加します

threads.append(thread1)

threads.append(thread2)

# すべてのスレッドが完了するまで待ちます

for t in thread:

t.join()

print "メインスレッドを終了しています"

スレッド優先キュー (キュー)

Python の Queue モジュールは同期スレッドを提供します-safe キュー クラス。FIFO (先入れ先出し) キュー Queue、LIFO (後入れ先出し) キュー LifoQueue、および優先キュー PriorityQueue を含みます。これらのキューはロック プリミティブを実装しており、マルチスレッドで直接使用できます。キューを使用して、スレッド間の同期を実現できます。

Queue モジュールで一般的に使用されるメソッド:

Queue.qsize() キューのサイズを返します

Queue.empty() キューが空の場合は True を返し、それ以外の場合は False を返します

Queue.full()キューがいっぱいの場合は True を返し、それ以外の場合は False を返します

Queue.full は maxsize のサイズに対応します

Queue.get([block[, timeout]]) でキューを取得し、タイムアウト待ち時間

Queue.get_nowait() Queue.get(False)と同等

Queue.put(item)はキューに書き込み、タイムアウト待ち時間

Queue.put_nowait(item)はQueue.put(item, False)と同等

Queue.task_done( ) 作業が完了すると、Queue.task_done() 関数はタスクが完了したキューにシグナルを送信します

Queue.join() は実際には、他の操作を実行する前にキューが空になるまで待機することを意味します

例:

#!/usr/bin/python

インポートキュー

インポートスレッド

インポート時間

exitFlag = 0

クラススレッド (スレッド.スレッド):

def __init__(self, threadID, name, q):

threading.Thread.__init__(self)

self.threadID = threadID

process_data(self.Name, Self.q )

Print "Exning"+Self.name

Def Process_data (ThreadName, Q):

While Not Exitflag:

Queuelock.acquire ()

If not workque.emptt Y (Y ( ):

️ ;S Print "%s処理%s"%(threadName, data)

else:

queuelock.release ()

time.sleep (1)

ThreadList = ["Thread-", "Thread- 2", "スレッド-3"]

nameList = ["1", "Two", "Three", "Four", "Five"]

queueLock = threading.Lock()

workQueue = Queue.Queue (10)

threads = []

threadID = 1

# threadListのtNameに対して新しいスレッド

を作成します:

thread = myThread(threadID, tName, workQueue)

thread.start()

スレッド。 append(thread)

threadID += 1

# nameList の単語に対してキューを埋める

queueLock.acquire()

:

workQueue.put(word)

queueLock.release()

# キューがクリアされるのを待ちます

while not workQueue.empty():

pass

# スレッドに終了する時間が来たことを通知します

exitFlag = 1

# すべてのスレッドがクリアされるのを待ちますcomplete

for t in thread:

t.join()

print "Exiting Main Thread"

上記のプログラムの実行結果:

Starting Thread-1

Starting Thread-2

開始スレッド - 3

スレッド - 1 処理 1 つ

スレッド 2 処理 2 つ

スレッド 3 処理 3 つ

スレッド 1 処理 4 つ

スレッド 2 処理 5 つ

終了スレッド 3

終了スレッド-1

スレッドを終了します-2

メインスレッドを終了します


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:Python XML解析次の記事:Python XML解析