1、一些概念多線程
線程,顧名思義,就是一條流水線工做的過程(流水線的工做須要電源,電源就至關於cpu),而一條流水線必須屬於一個車間,一個車間的工做過程是一個進程,車間負責把資源整合到一塊兒,是一個資源單位,而一個車間內至少有一條流水線。ide
多線程(即多個控制線程)的概念是,在一個進程中存在多個線程,多個線程共享該進程的地址空間,至關於一個車間內有多條流水線,都共用一個車間的資源。例如,北京地鐵與上海地鐵是不一樣的進程,而北京地鐵裏的13號線是一個線程,北京地鐵全部的線路共享北京地鐵全部的資源,好比全部的乘客能夠被全部線路拉。spa
那麼,爲何要開線程呢?當咱們須要多個程序同時運行,可是還須要數據共享——開進程的話能保證第一點可是數據不能共享,因此要用同一個進程下的多個線程。線程
因此說,進程只是用來把資源集中到一塊兒(進程只是一個資源單位,或者說資源集合),而線程纔是cpu上的執行單位。光開進程不能工做,須要進程裏開線程才能正常工做,當一個進程開啓時,對應的一個線程會隨着同時開啓。一個進程能夠開啓多個線程————一個進程內的多個線程是共享數據的。開進程的開銷遠遠比開進程的開銷大,由於開進程得申請空間,開線程是基於開好的空間進行的。3d
2、開啓線程的兩種方式code
2.1 利用threading模塊下的Thread類:對象
# -*- coding: utf-8 -*- # -*- Author: WangHW -*- from threading import Thread import time import os def work(name): print('%s is running...id:%s'%(name,os.getpid())) time.sleep(1) print('%s is done...'%os.getpid()) if __name__ == '__main__': w = Thread(target=work,args=('whw',)) #開啓線程開始start方法 w.start() #主進程開啓是默認開啓了主線程,進程要想執行必需要有一個線程 #如今有一個進程兩個線程 #執行角度看這是主線程,資源角度講是主進程 print('主線程~')
2.2 利用類的繼承blog
# -*- coding: utf-8 -*- # -*- Author: WangHW -*- from threading import Thread import time import os class MYThread(Thread): def __init__(self,name): super().__init__() self.name = name def run(self): print('%s is running...id:%s' % (self.name,os.getpid())) time.sleep(1) print('%s is done...'% os.getpid()) if __name__ == '__main__': w = MYThread('whw') #start w.start() print('主線程')
3、線程與進程的區別:繼承
3.1 首先,從開銷的角度來說,開進程的開銷要遠遠大於開線程的開銷,由於開進程涉及到空間的建立,而開啓線程僅僅是在既有的空間的基礎上進行的;其次,同一個進程的各個線程之間是共享資源的,而不一樣的進程之間的資源是不共享的。進程
3.2 咱們如今驗證一下進程與線程的資源共享問題:
3.2.1 對於多線程來講:,咱們全局定義的n=100,而通過子線程t1的處理,n的值無論是在主線程仍是子線程都變成了0:
# -*- coding: utf-8 -*- # -*- Author: WangHW -*- from threading import Thread import time import os n = 100 #方法 def work(name): print('%s is running...id:%s'%(name,os.getpid())) global n n = 0 time.sleep(2) print('%s is done...'%os.getpid()) print('%s 內n的值爲:%s'%(os.getpid(),n)) if __name__ == '__main__': t1 = Thread(target=work,args=('子線程1',)) t1.start() t1.join() print('主'.center(10,'*')) print('主的n:',n)
線程程序的運行結果:
3.2.2 對於多進程來講,多個進程之間是不共享資源的:
# -*- coding: utf-8 -*- # -*- Author: WangHW -*- from multiprocessing import Process import time import os n = 100 #方法 def work(name): print('%s is running...id:%s'%(name,os.getpid())) global n n = 0 time.sleep(2) print('%s is done...'%os.getpid()) print('%s 內n的值爲:%s'%(os.getpid(),n)) if __name__ == '__main__': p1 = Process(target=work,args=('子進程1',)) p1.start() p1.join() print('主'.center(10,'*')) print('主的n:',n)
運行結果以下:
4、Thread對象的其餘屬性及方法:
Thread對象支持下列需求的方法:
4.1 找到當前線程的名字與id:
找到當前線程的名字須要引入current_thread類,用到getName方法:
print(current_thread().getName())
而找id還能夠利用os模塊小的getpid方法:
print(os.getpid())
4.2 查看當前存活的線程的名字與數量(注意須要在threading模塊導入相應的類):
# 查看當前存活的線程 print(active_count()) #查看當前存活的具體的線程 print(enumerate())
4.3 查看線程是否存活:
#造線程對象的時候能夠用name=寫名字 t = Thread(target=work,name='whw1') t.start() #查看線程是否存活 print(t.is_alive())
4.4 設置線程名字
#造線程對象的時候能夠用name=寫名字 t = Thread(target=work,name='whw1') t.start() #設置線程的名字 t.setName('兒子線程1') #設置主線程的名字 current_thread().setName('主線程')
4.5 固然,還有join方法,等子線程執行完畢再執行主線程
#造線程對象的時候能夠用name=寫名字 t = Thread(target=work,name='whw1') t.start() #等子線程執行完再執行主線程 t.join() #找到主線程的名字--默認MainThread print('主'.center(10,'*'),current_thread().getName())
具體的完整代碼以及執行效果以下:
# -*- coding: utf-8 -*- # -*- Author: WangHW -*- from threading import Thread,current_thread,active_count,enumerate import os import time def work(): #找到當前線程的名字與id print('%s is running...id:%s:'%(current_thread().getName(),os.getpid())) time.sleep(2) print('%s is done...'%current_thread().getName()) if __name__ == '__main__': #造線程對象的時候能夠用name=寫名字 t = Thread(target=work,name='whw1') t.start() # 查看當前存活的線程 print('當前存活線程個數:',active_count()) #查看當前存活的具體的線程 print('當前存活線程的具體信息:',enumerate()) #查看線程是否存活 print('子線程是否存活?',t.is_alive()) #設置線程的名字 t.setName('兒子線程1') #等子線程執行完再執行主線程 t.join() # 查看子線程是否存活 print('子線程是否存活?',t.is_alive()) #查看當前存活的線程 print('當前存活線程個數:',active_count()) # 查看當前存活的線程 print('當前存活線程的具體信息:',enumerate()) #設置主線程的名字 current_thread().setName('主線程') #找到主線程的名字--默認MainThread print('主'.center(10,'*'),current_thread().getName())
執行效果: