Pythonマルチスレッド学習(上)

16241 ワード

最近pythonマルチスレッドを勉強していて、エッセイを書いて復習しました.また、「Pythonコアプログラミング」という本を強くお勧めします.この本ではpythonの進級を学ぶことができます.
一.基本概念:
1.スレッド:
スレッドは軽量レベルのプロセスとも呼ばれ、スレッド間で情報共有が可能であり、スレッドはメインプロセスまたは「メインスレッド」のミニプロセスと見なすことができる.
2.プロセス:
プロセスは重量級プロセスとも呼ばれ、プロセス間は独立しており、プロセス間共有情報は「プロセス間通信(IPC)」によって行われる.
3.同期:
同期とは、1つのタスクが完了した後、もう1つのタスクが続いて行われることです.例えば、食堂で食事をしていると、1番の窓口の料理がおいしくて、たくさんの人が並んでいて、前の1つだけが食事をして、後の1つだけが食事をすることができます.
4.非同期:
非同期とは、複数のタスクが同時に行われることを意味します.例えば、食堂には食事の窓口がたくさんあり、多くの人が同時に食事をすることができます.
5. I/O:
I/Oはinput/outputの略で、読み書きを意味します.
6.I/O密集型コード(I/O bound):
I/O密集型とは、プログラムの読み書き操作が多く、計算が比較的少ないことを意味します.
7.計算密集型コード(CPU bound):
計算密集型とは,プログラムが主に計算を行い,読み書き操作が少ないことを指す.
8.同時および並列:
同時CPU数
パラレルCPU数>スレッド数、パラレルとは複数のタスクが同時に実行されることを意味します.
 
二.pythonとスレッド:
pythonコードの実行はpython仮想マシン(解釈器メインサイクル)によって制御される.
PythonにはGIL(グローバル解釈ロック)があり、プログラムが実行されているスレッドが1つしかないことを制御します.
GILロック実行プロセス:
ロック
実行
レリーズ
最初のステップに戻ります.
pythonがマルチスレッドを実行すると、実際には同じ時間間隔でタスクが実行され、各タスクはしばらく実行され、その後保留され、次の実行で最後まで実行され、最初から最後まで往復され、終了します.
pythonはI/O密集型に対して計算密集型よりも友好的である.理由:pythonはI/O密集型プログラムを実行する時、主にファイルの読み書きを行って、計算が少なくて、各任務は計算する同時にその他の完成する計算の読み書きを行うことができて、計算密集型は計算に対して比較的に多くて、ずっとCPUを占有して、処理効率が高くなくて、だから計算密集型に対して友好的ではありません.
三.threadingモジュール
マルチスレッドにはthreadモジュールとthreadingモジュールがあります.threadモジュールは、マルチスレッドを実行する場合、ロックをかけずにメインスレッドが終了し、サブスレッドがまだ終了していない場合、サブスレッドが強制的に停止し、実行結果が得られない.マルチスレッド学習ではthreadingモジュールの使用を推奨します.
1.スレッドの追加:threading.Thread(target=関数名、args=(入力が必要なパラメータ))
Threadクラスはnameを入力し、スレッドに名前を付けることもできます.
2.スレッドがアクティブになっているかどうかを判断する:is_alive()
3.取得スレッド数:threading.active_count()
4.現在のスレッドの取得:threading.current_thread()
5.スレッド名を取得する:.name
6.スレッド待ち:.join()
待機と待機なし:
待機:
 1 def a_1():
 2     print('aaaaa')
 3     time.sleep(3)
 4     print('aaaaa')
 5 def a_2():
 6     print('bbbbb')
 7     time.sleep(5)
 8     print('bbbbb')
 9 def main():
10     print('....start....')
11     t1 = threading.Thread(target=a_1)
12     t2 = threading.Thread(target=a_2)
13     t1.start()
14     t2.start()
15     print('....end....')
16 
17 if __name__ == '__main__':
18     main()
19 
20 
21 22 
23 ....start....
24 aaaaa
25 bbbbb
26 ....end....
27 aaaaa
28 bbbbb
29 
30 Process finished with exit code 0

実行結果から、待機を追加しない場合、実行結果は私たちが望んでいる結果ではないことがわかります.
次は使いません.join()の待機:
def main():
    print('....start....')
    t1 = threading.Thread(target=a_1)
    t2 = threading.Thread(target=a_2)
    t1.start()
    t2.start()
    time.sleep(8)
    print('....end....')

if __name__ == '__main__':
    main()

    :
....start....
aaaaa
bbbbb
aaaaa
bbbbb
....end....

Process finished with exit code 0

timeを追加する.sleep()文は、サブスレッドの実行が終了するまでメインスレッドを待機させ、次の操作を実行します.印刷内容はすべて...start....と...end...の間に表示されます.
次は運用です.join()で待ちます.
def main():
    print('....start....')
    t1 = threading.Thread(target=a_1)
    t2 = threading.Thread(target=a_2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print('....end....')

if __name__ == '__main__':
    main()

    :
....start....
aaaaa
bbbbb
aaaaa
bbbbb
....end....

Process finished with exit code 0

この結果から、sleep()とjoin()を追加する効果は同じであるが、使用を推奨することがわかる.join()は、プログラムを実行するときにsleep()で待つので、待ち時間も知らなければならないので、面倒です.join()の方が便利です.
 
 
 
スレッドの作成方法:
<1>Threadクラスへの入力関数
<2>Threadクラスにインスタンスクラスを入力
<3>サブクラスを作成し、Threadクラスを継承し、関数をサブクラスに転送
................................................
................................................
マルチスレッドを使用しない場合:
import datetime
def num_1():
print('start...1')
time.sleep(2)
print('end...1')
def num_2():
print('start...2')
time.sleep(4)
print('end...2')

def main():
a = datetime.datetime.now()
print('.............start...........')
num_1()
num_2()
print('..............end............')
b = datetime.datetime.now()
p = (b - a).seconds
print(' %s ' % p)
if __name__ == '__main__':
main()

2つの関数を作成し、それぞれ異なる内容を印刷し、プログラムの実行が完了したときに印刷実行時間を指定します.
........................................
........................................
<1>の場合
次に、サンプルコードを示します.join()は、メインスレッドがサブスレッドの完了を待ってから次の操作を実行します.
 1 import threading
 2 import datetime
 3 #    (1)
 4 def num(nu,se):
 5     print('%s  start' % nu)
 6     time.sleep(se)
 7     print('%s  end' % nu)
 8 
 9 time_list = [2,4]
10 def main():
11     a = datetime.datetime.now()
12     print('.....start.....')
13     thread_list = []
14     for x in range(len(time_list)):
15         t = threading.Thread(target=num,args=(x,time_list[x]))
16         thread_list.append(t)
17     for x in thread_list:
18         x.start()
19     for x in thread_list:
20         x.join()
21     print('.....end.....')
22     b = datetime.datetime.now()
23     p = (b - a).seconds
24     print('  %s ' % p)
25 if __name__ == '__main__':
26     main()

 
<2>インスタンスクラスを追加します.
class New_1():
    def __init__(self,num,se):
        self.num = num
        self.se = se
    def __call__(self):
        return self.num(*self.se)
    pass

def main():
    a = datetime.datetime.now()
    print('...start...')
    thread_list = []
    for x in range(len(time_list)):
        t = threading.Thread(target=New_1(num,(x+1,time_list[x])))
        thread_list.append(t)
    for x in thread_list:
        x.start()
    for x in thread_list:
        x.join()
    print('...end...')
    b = datetime.datetime.now()
    p = (b-a).seconds
    print('  %s ' % p)
    
if __name__ == '__main__':
    main()


...start...1 start2 start1 end2 end...end...4秒の実行
 
    

Process finished with exit code 0

3.继承Thread类,将内容传递进子类中。

下面是代码:

#    (1)
def num(nu,se):
    print('%s  start' % nu)
    time.sleep(se)
    print('%s  end' % nu)
time_list = [2,4]
class New_2(threading.Thread):
    def __init__(self,num,se):
        super().__init__()
        self.num = num
        self.se = se
# run() , , run(), , 。 def run(self): return self.num(*self.se) pass def main(): a = datetime.datetime.now() print('...start...') thread_list = [] for x in range(len(time_list)): t = New_2(num,(x,time_list[x])) thread_list.append(t) for x in thread_list: x.start() for x in thread_list: x.join() print('...end...') b = datetime.datetime.now() p = (b-a).seconds print(' %s ' % p) if __name__ == '__main__': main() : ...start... 0 start 1 start 0 end 1 end ...end... 4 Process finished with exit code 0

以上の3つのスレッドを追加する方法については、自分の好みに合わせて自分で選択し、他のことを理解すればよい.
 
間違った点があれば、皆さんのご指摘をお願いします.
皆さんの読書に感謝します.
 
転載先:https://www.cnblogs.com/sniper-huohuohuo/p/8777374.html