シーンを設定すると、ユーザーは、複数のタスクを追加し、これらのタスクのバックグラウンドで処理タスクを実行するためのボタンをクリックして、タスクの成否を決める、タスクは時間がかかるので、そのタスクを処理する複数のスレッドの使用
考えてみましょう:
スレッドが開始され、実装タスクの結果を取得するには?
コードを見てください:
インポートスレッディング インポート時の クラス(threading.Threadの)TaskThread: "" " クラスをスレッドに関連する処理タスク " "" DEF __init__(セルフ、FUNC、引数= ()): スーパー(TaskThread、セルフ)__init__ () self.func FUNC = #のタイプの実行するタスク self.args =引数 #入ってくるパラメータに DEF :RUN(セルフ) #のスレッドクラスのインスタンスは、開始を呼び出す()メソッドは、特定のタスク非同期行うためにここに定義されたrun()メソッド、実行されます 印刷(" スタートFUNC {} " .format(self.func。__name__)) #プリントタスク名、メソッド名でname__ .__ self.result = self.func(* self.args) #は、タスクの実行結果self.result変数に代入される DEFのget_result(セルフ): #は、メソッド名、メソッドは、タスクの実行機能の結果を返す変更します必ずしもget_resultない 試みを: リターンself.result 除く:EX AS例外 印刷(EX) リターン " ERROR " DEFのtask_type1(TASK_ID、タスク名): 印刷(" 作業を開始し、名前:{}、ID:{} " .format(タスク名、TASK_ID)) time.sleep( 2 ) 印刷("タスク終了、名:{}、ID:{} 」.format(TASK_NAME、TASK_ID)) を返すTASK_ID thread_pool = [] #のスレッドのインスタンスを保持するためのリスト のための I にレンジ(10 ): #はスレッド目標ループ作成 スレッド= TaskThread (task_type1、引数=(I + 1、「ペイ」)) #は、プールにスレッドオブジェクトを追加します (スレッド)がthread_pool.append #のスタートスレッド実行タスク Thread.start() のためのスレッドでthread_pool: #重要なステップは、なぜ必要があります参加するには Thread.join() #でスレッドプールからの結果を得る 印刷(" 結果:{} " .format(thread.get_result()))
結果:
funcはtask_type1開始 :有料、ID:タスク、名前開始 1 task_type1開始funcを :有料、ID:タスク、名前開始 2 task_type1開始funcを タスクを起動し、名前:支払う、ID: 3 開始funcがtask_type1 タスクを起動し、名前:支払う、ID : 4 スタートfuncがtask_type1 、名前をタスクを開始します支払う、ID: 5 スタートfuncがtask_type1 :ID、支払う:名前、タスクを開始する 6 スタートfuncがtask_type1 :ID、支払う:名前は、タスクを起動する 7 スタートfuncがtask_type1 、名前のタスクを開始:有料、ID: 8 のスタートfuncがtask_type1 支払う、ID:名前、タスクを開始 9 スタートFUNCのtask_type1 スタートタスク、名前:支払う、ID: 10 エンドタスク名:支払う、ID: 4つの 端タスク名:支払う、ID: 2 端タスク名:支払う、ID: 1つの エンドタスク名:支払う、ID: 5つ の端タスク名:支払う、ID: 8 エンドタスク名:支払う、ID: 3 結果: 1つの 結果: 2つの 端タスク名:支払う、ID: 9 結果: 3 結果: 4 結果: 5つの エンドタスク名:支払う、ID: 10の エンドタスク名: 、IDを支払う: 6 結果: 6つの エンドタスク、名前:支払う、ID: 7 結果: 7 結果: 8 結果: 9 の結果を:10
上記のコードは)スレッド実行タスクを作成し、タスクを取得し、キーポイントは、スレッドクラスはタスク関数の戻り値を取得するために使用ge_resultメソッドを実装し、そして(thread.join使用していることです実装どのスレッドが存在しない場合、これは、必見です.join()がどうなるかになりますか?
コメント:thread.join()と、コードを再実行します。
funcはtask_type1開始 :有料、ID:タスク、名前開始 1 task_type1開始funcを :有料、ID:タスク、名前開始 2 task_type1開始funcを タスクを起動し、名前:支払う、ID: 3 開始funcがtask_type1 タスクを起動し、名前:支払う、ID : 4 スタートfuncがtask_type1 、名前をタスクを開始します支払う、ID: 5 スタートfuncがtask_type1 :ID、支払う:名前、タスクを開始する 6 スタートfuncがtask_type1 :ID、支払う:名前は、タスクを起動する 7 スタートfuncがtask_type1 、名前のタスクを開始:有料、ID: 8 のスタートfuncがtask_type1 支払う、ID:名前、タスクを開始 9 スタートFUNCのtask_type1 スタートタスク、名前:支払う、ID: 10 「TaskThread 」オブジェクトには属性がありません「結果」 の結果を:ERROR 「TaskThread 」オブジェクトには属性がありません「結果」 の結果を:ERROR 「TaskThread 」オブジェクトは属性がありません「結果」 の結果を:ERROR 「TaskThread 」オブジェクトが属性を持っていない「結果」 の結果を:ERRORは 「TaskThread 」オブジェクトには属性がありません「結果」 ERROR:結果を "TaskThread」オブジェクトは、何の属性がありません「結果」 の結果を:ERROR 「TaskThread 」オブジェクトが属性を持っていない「結果」 結果:ERROR 「TaskThread 」オブジェクトは属性がありません「結果」 の結果を:ERROR 「TaskThread 」オブジェクトは属性がありません「結果」 の結果を: ERROR 「TaskThread 」オブジェクトには属性がありません「結果」 の結果を:ERRORの 終了タスク、名前:支払う、IDを:1 エンドタスク、名前:支払う、ID: 3つの エンドタスク、名前:支払う、ID: 2 エンドタスク、名前:支払う、ID: 5 エンドタスク、名前:支払う、ID: 6つの エンドタスク、名前:支払う、ID: 7 エンドタスク、名前:支払う、ID: 4つの エンドタスク、名前:支払う、ID: 8つの エンドタスク、名前:支払う、ID: 9つの エンドタスク、名前:支払う、ID: 10
あなたが参加していない場合は、私たちがなぜあるこの結果を、得ましたか。
runメソッドでself.resultは、唯一self.func実行後、self.resultbが唯一の割り当てだったので、これは私たちがget_resultを呼び出すときに、実行する方法は、終了を実行していない、自然に割り当てられていないself.resultので、投げる、あります「TaskThread」オブジェクトには属性「持っていない結果」 例外を。
通常self.result得ることができ、後に参加するのはなぜ?
マルチスレッドのどのような原則を理解することが必要である:
1.処理が開始されると、それはデフォルトのメインスレッドを生成します、複数のスレッドを設定するときに、スレッドは、プログラムの実行フローの最小単位であるため、メインスレッドが複数の子スレッドを作成し、中Pythonで、(実際には、は、setdaemon(偽))、その任務の実装が完了した後にメインスレッド、デフォルトから撤退し、その後、子スレッドは、そのタスクを実行し続けます
は、setdaemon(真)メソッドは、子スレッドを設定した場合2.デーモンスレッドは、メインスレッドで実行が完了すると、スレッド全体をすべて実行終了し、状況が発生する可能性がある子供はタスクがまだ完全に終わりを実装されていないスレッドということです、それは停止を余儀なくされたが、もちろん、これは我々が見たいものではありません
3.私たちは、あなたが)(結合を使用する必要があり、その後、メインスレッドの終了後に結果が完成された子スレッドの実行を待ってブロックされて見たいと思って
、その背後にあるスタート()に()が参加することができますか?
試してみてください:
Thread.start()
Thread.join()
の結果:
funcはtask_type1開始 支払う、ID:タスク、名前開始 1 :終了タスク、名前:支払う、ID 1 task_type1開始funcを 支払う、ID:タスク、名前開始 2つの エンドタスク、名前:支払う、ID: 2 開始FUNCのtask_type1の 開始をタスク、名前:支払う、ID: 3つの エンドタスク、名前:支払う、ID: 3 開始funcがtask_type1 タスクを起動し、名前:支払う、ID: 4つの エンドタスク、名前:支払う、ID: 4 スタートfuncがtask_type1 開始タスク、名前:支払う、ID: 5つの エンドタスク、名前:支払う、ID: 5 開始FUNC task_type1 支払う、ID:タスク、名前開始 6つの エンドタスク、名前:支払う、ID: 6 funcはtask_type1開始 支払う、ID:タスク、名前開始 7 :最後のタスク、名前:支払う、ID 7 task_type1開始funcを 支払う、ID:タスク、名前開始 8つの エンドタスク、名前:支払う、ID: 8 開始FUNCのtask_type1の 開始をタスク、名前:支払う、ID: 9 エンドタスク、名前:支払う、ID: 9 スタートfuncがtask_type1 タスクを起動し、名前:支払う、ID: 10の 終了タスク、名前:支払う、ID: 10 結果: 1つの 結果: 2 結果: 3 結果: 4 結果: 5 結果: 6 結果: 7 結果: 8 結果: 9 結果: 10
結果は得たが、それぞれが(開始後の参加)エンドの実装をブロックする子スレッドが次のサイクルを知るようになった、そして、このようなサイクルの効率はシングルスレッド、タスクの実行スレッドであれば2秒に相当し、そのような方法でされます参加の役割は()であるため、10のタスク20代、明らかに間違った使い方を実行します。 他のサブスレッドの実装が終了した後、メインスレッドが終了するため、スレッドの同期を、メインスレッドのタスクの終了後、つまり、ブロックされた状態に入り、待機していました