Latest web development tutorials

python3マルチスレッド

同時に実行複数のスレッドは、マルチスレッド操作は、次のような利点があり、別のプログラムの数のようになります。

  • スレッドを使用することに対処するためにバックグラウンドにタスクに長いプログラムを占めることができます。
  • 例えば、ユーザは、いくつかのイベント処理をトリガするボタンをクリックするようにユーザーインターフェイスは、より魅力的かもしれ、あなたは、プロセスの進行状況を表示するプログレスバーを開くことができます
  • スピードを実行すると、加速する可能性が
  • そのようなデータを送受信するために、ユーザ入力、文書リテラシーやネットワークを待っているように実現いくつかのタスク、では、スレッドがより有用です。 この場合、我々はそのようなので、上のメモリ使用量とのようないくつかの貴重なリソースを、解放することができます。

実装プロセス内のスレッドとプロセスが異なっています。 それぞれが注文の履行のためのエントリ、終了シーケンスと手順を実行している別のスレッドがあります。 しかし、スレッドが独立して実行することはできないが、それは、アプリケーションによって制御される複数の実行スレッドを提供し、用途に応じて存在している必要があります。

各スレッドは、スレッドのコンテキストと呼ばれるCPUレジスタの彼自身のセットを持って、スレッドコンテキストは、スレッドのCPUレジスタの状態の最後の実行を反映しています。

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

  • スレッドが横取りすることができます(中断)。
  • 実行されている他のスレッドでは、スレッドは(も睡眠として知られている)停止状態のままに保持することができる - これは譲歩のスレッドです。

スレッドは分けることができます:

  • カーネルスレッド:オペレーティングシステムのカーネル作成および破棄。
  • ユーザスレッド:ユーザプログラムがスレッドを実装し、カーネルのサポートとを必要としません。

python3共通のスレッド2のモジュール:

  • _thread
  • スレッド(推奨)

スレッドモジュールが放棄されています。 ユーザーは、代わりにthreadingモジュールを使用することができます。 だから、のpython3でもはや「スレッド」モジュールを使用することはできません。 互換性のために、のpython3スレッドは「_thread」の名前を変更します。


Pythonのスレッドを学び始めます

次の2つの方法で使用Pythonのスレッド:スレッドオブジェクトをラップするための関数やクラスを持ちます。

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

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

パラメータ説明:

  • 機能 - スレッド関数。
  • 引数 - 関数に渡されたスレッドパラメータが、彼はタプル型でなければなりません。
  • kwargsから - オプション。

例:

#!/usr/bin/python3

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()) ))

# 创建两个线程
try:
   _thread.start_new_thread( print_time, ("Thread-1", 2, ) )
   _thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
   print ("Error: 无法启动线程")

while 1:
   pass

次のように上記のプログラムの出力結果は次のとおりです。

Thread-1: Wed Apr  6 11:36:31 2016
Thread-1: Wed Apr  6 11:36:33 2016
Thread-2: Wed Apr  6 11:36:33 2016
Thread-1: Wed Apr  6 11:36:35 2016
Thread-1: Wed Apr  6 11:36:37 2016
Thread-2: Wed Apr  6 11:36:37 2016
Thread-1: Wed Apr  6 11:36:39 2016
Thread-2: Wed Apr  6 11:36:41 2016
Thread-2: Wed Apr  6 11:36:45 2016
Thread-2: Wed Apr  6 11:36:49 2016

上記の処理を実行した後に終了するには、Ctrl + Cを押すことができます。


スレッドモジュール

python3は2標準ライブラリ_threadとスレッド通すためのサポートを提供しています。

_threadはスレッディング機能モジュールはまだ比較的限られていると、それが比較され、低レベル、元のスレッドとシンプルなロックを提供します。

threadingモジュールに加えて、他の方法は、すべてのメソッド_threadモジュールが含まれていますが、また、提供します:

  • threading.currentThread():現在のスレッドの変数を返します。
  • threading.enumerateは():含まれている実行中のスレッドのリストを返します。 実行中のスレッドが終了する前に開始し、それは開始前と終了後にスレッドが含まれていません指します。
  • threading.activeCountは():実行中のスレッドの数を返します、とlen(threading.enumerate())と同じ結果を持っています。

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

  • 実行():アクティブなスレッドの方法を示すために。
  • 開始():スレッドの活動を開始。

  • 参加する([時刻]):スレッドが中止されるまで待ちます。通常の終了または未処理の例外をスロー - - スレッドのjoin()メソッドまで、呼び出したスレッドは、サスペンションと呼ばれるこのブロックまたはオプションのタイムアウトが発生します。
  • IsAliveのは():スレッドがアクティブで返します。
  • getName():スレッドの名前を返します。
  • setName():スレッド名を設定します。

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

私たちは、直接通話開始後、threading.Threadクラスから新しいサブクラスを継承し、それは、スレッドのrun()メソッドを呼び出して新しいスレッドを開始する()メソッドをインスタンス作成することができます。

#!/usr/bin/python3

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 ("开始线程:" + self.name)
        print_time(self.name, self.counter, 5)
        print ("退出线程:" + self.name)

def print_time(threadName, delay, counter):
    while counter:
        if exitFlag:
            threadName.exit()
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主线程")

次のように上記プログラムの実行結果です。

开始线程:Thread-1
开始线程:Thread-2
Thread-1: Wed Apr  6 11:46:46 2016
Thread-1: Wed Apr  6 11:46:47 2016
Thread-2: Wed Apr  6 11:46:47 2016
Thread-1: Wed Apr  6 11:46:48 2016
Thread-1: Wed Apr  6 11:46:49 2016
Thread-2: Wed Apr  6 11:46:49 2016
Thread-1: Wed Apr  6 11:46:50 2016
退出线程:Thread-1
Thread-2: Wed Apr  6 11:46:51 2016
Thread-2: Wed Apr  6 11:46:53 2016
Thread-2: Wed Apr  6 11:46:55 2016
退出线程:Thread-2
退出主线程

スレッド同期

共通のデータ変更の複数のスレッドが、予期しない結果が発生する可能性がある場合は、データの正確性を確保するために、我々は複数のスレッドを同期する必要があります。

ロックとRLOCKを使用して、スレッドオブジェクトは、単純なスレッドの同期を達成することができ、2つのオブジェクトがメソッドを取得してメソッドをリリースする必要があり、一つのスレッドだけの運転データを可能にそれぞれを必要とする人のために、それはの操作の取得および解放の方法で配置することができます部屋。 次のように:

利点をマルチスレッド化すると、それは同時に複数のタスクを実行できることです(少なくとも、このように感じています)。 スレッドがデータを共有する必要がある場合には、データ同期の問題が存在しなくてもよいです。

すべての要素のリストゼロで、バックからスレッド「セット」前面に一つにすべての要素を、リストや印刷を読み取る担当前後からスレッド「印刷」:ケースを考えてみましょう。

その後、スレッドは「設定」のスレッド「印刷」は、リストを印刷するときに変化し始めたことがあり、それは、データが同期されていないされて半分0の半分出力、であろう。 このような状況を回避するために、我々は、ロックの概念を導入します。

ロックとロック解除 - ロックは、2つの状態があります。 そのようなあなたが最初のロックを取得する必要があり、共有データにアクセスするための「設定」などのスレッドたびに、同期ブロックであるあなたは、すでに別のスレッドがある場合は、そのような「プリント」とは、ロックアップを取得するために、スレッドが「設定」させ、一時停止、;スレッドまで待ちます」印刷を続行するには、set ""アクセスが完了すると、ロックのリリース後、スレッドを聞かせて」。

あなたはすべての出力0または1のいずれか完全な出力の一覧を印刷するとき、このプロセスの後、もはや半分恥ずかし0 1半分は表示されません。

例:

#!/usr/bin/python3

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 ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # 释放锁,开启下一个线程
        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 = []

# 创建新线程
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 threads:
    t.join()
print ("退出主线程")

上記のプログラムは、出力は次のようになります。

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Apr  6 11:52:57 2016
Thread-1: Wed Apr  6 11:52:58 2016
Thread-1: Wed Apr  6 11:52:59 2016
Thread-2: Wed Apr  6 11:53:01 2016
Thread-2: Wed Apr  6 11:53:03 2016
Thread-2: Wed Apr  6 11:53:05 2016
退出主线程

スレッドのプライオリティキュー(待ち行列)

Pythonのキューモジュールは、同期、FIFO(先入れ先出し)キューキュー、LIFO(うち最初の、の最後の)キューLifoQueue、およびプライオリティキューの優先度つきキューなどのスレッドセーフなキュークラスを提供しています。

これらのキューは、あなたがスレッド間の同期を達成するためにキューを使用することができ、ロックプリミティブはマルチスレッドで直接使用することができます実装されています。

キューのモジュール一般的に用いられている方法:

  • Queue.qsize()キューのサイズを返します。
  • Queue.empty()キューが空の場合は、TRUE、FALSE、またはその逆を返します。
  • キューがいっぱいになるとQueue.full()、TRUE、FALSE、またはその逆を返します
  • サイズおよびMAXSIZE Queue.fullに対応
  • Queue.getは([ブロック[、タイムアウト]])キュー、タイムアウト待機時間を取得します。
  • Queue.getむしろQueue.get_nowait()(偽)
  • Queue.put(アイテム)書き込みキュー、タイムアウト待ち時間
  • Queue.put_nowait(アイテム)かなりQueue.put(アイテム、偽)
  • Queue.task_done()は、作業の完了後、Queue.task_done()関数は、タスクへの信号キューを完了した送信します
  • Queue.join()は実際にキューが空になるまで、他の操作を実行する手段と

例:

#!/usr/bin/python3

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 ("开启线程:" + self.name)
        process_data(self.name, self.q)
        print ("退出线程:" + 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

# 创建新线程
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# 填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

# 通知线程是时候退出
exitFlag = 1

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

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

开启线程:Thread-1
开启线程:Thread-2
开启线程:Thread-3
Thread-3 processing One
Thread-1 processing Two
Thread-2 processing Three
Thread-3 processing Four
Thread-1 processing Five
退出线程:Thread-3
退出线程:Thread-2
退出线程:Thread-1
退出主线程