Contents
Pythonマルチスレッドプログラミング
複数のスレッドを実行することは、いくつかの異なるプログラムを同時に実行することに似ています。複数のスレッドを実行する利点として、、、。
- プロセス内の複数のスレッドは、メインスレッドとサブで同じデータスペースを共有するため、別々のプロセスである場合よりも簡単に情報を共有したり、相互に通信したりできる
- スレッドは軽量プロセスと呼ばれることもあり、多くのメモリは必要ありません。
スレッドには、開始、実行順序、および結論があります。現在の進行状況を把握する追跡ポインタを持っています
- 先取り可能(中断)
- 他のスレッドが実行されている間、一時的に保留にすることもできます(スリーピングとも呼ばれます)。これは降伏と呼ばれます。
新しいスレッドの開始
別のスレッドを生成するには、スレッドモジュールで使用可能な次のメソッドを呼び出す必要があります。
thread.start_new_thread ( function, args[, kwargs] )
このメソッド呼び出しにより、LinuxとWindowsの両方で新しいスレッドを迅速かつ効率的に作成できます。
メソッド呼び出しは直ちに戻り、子スレッドが起動し、渡されたargのリストで関数を呼び出します。関数が戻ると、スレッドは終了します。
ここで、argsは引数のタプルです。引数を渡さずに関数を呼び出すには、空のタプルを使用します。kwargsはキーワード引数のオプション辞書です。
例
#!/usr/bin/python import thread import time #スレッドの関数を定義する def print_time( threadName, delay): count = 0 while count < 5: 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, ) ) except: print "Error: unable to start thread" while 1: pass
上記のコードを実行すると、次の結果が生成されます。
Thread-1: Thu Jan 22 15:42:17 2009 Thread-1: Thu Jan 22 15:42:19 2009 Thread-2: Thu Jan 22 15:42:19 2009 Thread-1: Thu Jan 22 15:42:21 2009 Thread-2: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:25 2009 Thread-2: Thu Jan 22 15:42:27 2009 Thread-2: Thu Jan 22 15:42:31 2009 Thread-2: Thu Jan 22 15:42:35 2009
スレッディングモジュール:
Python 2.4に含まれている新しいスレッディングモジュールは、前のセクションで説明したスレッドモジュールよりもはるかに強力な、高いレベルのスレッドサポートを提供します。
スレッドモジュールは、すべてのメソッド公開するスレッドのモジュールをし、いくつかの追加メソッドを提供します。
- threading.activeCount():アクティブなスレッドオブジェクトの数を返します。
- threading.currentThread():呼び出し元のスレッドコントロール内のスレッドオブジェクトの数を返します。
- threading.enumerate():現在アクティブなすべてのスレッドオブジェクトのリストを返します。
メソッドに加えて、スレッドモジュールにはスレッドを実装するThreadクラスがあります。Threadクラスが提供するメソッドは次のとおりです。
- run(): run()メソッドはスレッドのエントリポイントです。
- start(): start()メソッドは、runメソッドを呼び出してスレッドを開始します。
- join([time]): join()はスレッドが終了するのを待ちます。
- isAlive(): isAlive()メソッドは、スレッドがまだ実行中かどうかをチェックします。
- getName(): getName()メソッドはスレッドの名前を返します。
- setName(): setName()メソッドはスレッドの名前を設定します。
スレッディングモジュールを使用したスレッドの作成
スレッドモジュールを使用して新しいスレッドを実装するには、以下を実行する必要があります。
- Threadクラスの新しいサブクラスを定義します。
- 追加の引数を追加するには、__init __(self [、args])メソッドをオーバーライドします。
- 次に、run(self [、args])メソッドをオーバーライドして、起動時にスレッドが何をすべきかを実装します。
新しいThreadサブクラスを作成したら、そのインスタンスを作成してstart()を呼び出して新しいスレッドを開始することができます。start ()はrun()メソッドを呼び出します。
例
#!/usr/bin/python import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name print_time(self.name, self.counter, 5) print "Exiting " + self.name def print_time(threadName, counter, delay): while counter: if exitFlag: threadName.exit() time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() print "Exiting Main Thread"
上記のコードを実行すると、次の結果が生成されます。
Starting Thread-1 Starting Thread-2 Exiting Main Thread 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 Thread-1: Thu Mar 21 09:10:05 2013 Thread-1: Thu Mar 21 09:10:06 2013 Thread-2: Thu Mar 21 09:10:06 2013 Thread-1: Thu Mar 21 09:10:07 2013 Exiting 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
スレッドの同期
Pythonで提供されるスレッドモジュールには、スレッドを同期させるための簡単な実装ロックメカニズムが含まれています。新しいロックは、新しいロックを返すLock()メソッドを呼び出すことによって作成されます。
新しいロックオブジェクトのacquire(blocking)メソッドは、スレッドを同期させて強制的に実行するために使用されます。オプションのブロッキングパラメータを使用すると、スレッドがロックの取得を待機するかどうかを制御できます。
ブロッキングが0に設定されている場合、スレッドはロックを取得できない場合は0の値を返し、ロックを取得した場合は1を返します。blockingが1に設定されている場合、スレッドはブロックし、ロックが解放されるのを待ちます。
新しいロックオブジェクトのrelease()メソッドは、不要になったときにロックを解放するために使用されます。
例
#!/usr/bin/python import threading import time class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name # Get lock to synchronize threads threadLock.acquire() print_time(self.name, self.counter, 3) # Free lock to release next thread threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 threadLock = threading.Lock() threads = [] # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print "Exiting Main Thread"
上記のコードを実行すると、次の結果が生成されます。
Starting Thread-1 Starting Thread-2 Thread-1: Thu Mar 21 09:11:28 2013 Thread-1: Thu Mar 21 09:11:29 2013 Thread-1: Thu Mar 21 09:11:30 2013 Thread-2: Thu Mar 21 09:11:32 2013 Thread-2: Thu Mar 21 09:11:34 2013 Thread-2: Thu Mar 21 09:11:36 2013 Exiting Main Thread
マルチスレッド優先順位キュー
キューのモジュールを使用すると、アイテムの特定の数を保持することができる新しいキューオブジェクトを作成することができます。キューを制御するには以下の方法があります。
- get(): get()は、キューから項目を削除して返します。
- put(): putはアイテムをキューに追加します。
- qsize(): qsize()は現在キューに入っている項目の数を返します。
- empty(): empty()は、queueが空の場合にTrueを返します。それ以外の場合はFalse。
- full(): full()は、キューが満杯の場合はTrueを返します。それ以外の場合はFalse。
例
#!/usr/bin/python import Queue import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, q): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.q = q def run(self): print "Starting " + self.name process_data(self.name, self.q) print "Exiting " + self.name def process_data(threadName, q): while not exitFlag: queueLock.acquire() if not workQueue.empty(): data = q.get() queueLock.release() print "%s processing %s" % (threadName, data) else: queueLock.release() time.sleep(1) threadList = ["Thread-1", "Thread-2", "Thread-3"] nameList = ["One", "Two", "Three", "Four", "Five"] queueLock = threading.Lock() workQueue = Queue.Queue(10) threads = [] threadID = 1 # Create new threads for tName in threadList: thread = myThread(threadID, tName, workQueue) thread.start() threads.append(thread) threadID += 1 # Fill the queue queueLock.acquire() for word in nameList: workQueue.put(word) queueLock.release() # Wait for queue to empty while not workQueue.empty(): pass # Notify threads it's time to exit exitFlag = 1 # Wait for all threads to complete for t in threads: t.join() print "Exiting Main Thread"
上記のコードを実行すると、次の結果が生成されます。
Starting Thread-1 Starting Thread-2 Starting Thread-3 Thread-1 processing One Thread-2 processing Two Thread-3 processing Three Thread-1 processing Four Thread-2 processing Five Exiting Thread-3 Exiting Thread-1 Exiting Thread-2 Exiting Main Thread
次のページ⑧