1. 程式人生 > >python進程和線程

python進程和線程

name thread time() pro join() 單線程 count() img 快速

進程和線程
一、進程
進程是程序的分配資源的最小單元;一個程序可以有多個進程,但只有一個主進程;
二、線程
線程是程序最小的執行單元;一個進程可以有多個線程,但是只有一個主線程;
三、總結
一個程序至少有一個進程和一個線程;
程序的工作方式:
1.單進程單線程;2.單進程多線程;3.多進程多線程;
考慮到實現的復雜性,一般最多只會采用單進程多線程的工作方式;
四、為什麽要使用多線程
我們在實際生活中,希望既能一邊瀏覽網頁,一邊聽歌,一邊打遊戲。這時,如果只開一個進程,為了滿足需求,CPU只能快速切換進程,但是在切換進程時會造成大量資源浪費。所以,如果是多核CPU,可以在同時運行多個進程而不用進行進程之間的切換。
然而,在實際中,比如:你在玩遊戲的時候,電腦需要一邊顯示遊戲的動態,一邊你還得和同伴進行語音或語言進行溝通。這時,如果是單線程的工作方式,將會造成在操作遊戲的時候就無法給同伴溝通,在和同伴溝通的時候就無法操作遊戲。為了解決該問題,我們可以開啟多線程來共享遊戲資源,同時進行遊戲操作和溝通。
五、實例
場景一:並發依次執行
技術分享圖片
如上圖所示:有兩個簡單的函數,一個是聽音樂一個是打遊戲的函數。
如果按照之前的單線程方式,將會是先運行完聽音樂的函數再去運行打遊戲的函數,最後打印Ending。如下圖所示:
技術分享圖片
一共的運行時間是6秒。並且是只能單一按照順序依次去執行。而使用多線時,運行時間是3秒,並且是並行執行。
該情況下的多線程運行方式是,先創建線程1,再創建線程2,然後去啟動線程1和線程2,並和主線程同時運行。此種情況下,若子線程先於主線程運行完畢,則子線程先關閉後主線程運行完畢關閉;若主線程先於子線程結束,則主線程要等待所有的子線程運行完畢後再關閉。
該部分代碼塊:

import threading
import time
def music(name):
    print(‘%s begin listen music%s‘%(name,time.ctime()))
    time.sleep(3)
    print(‘%s stop listen music%s‘ % (name, time.ctime()))
def game(name):
    print(‘%s begin play game%s‘%(name,time.ctime()))
    time.sleep(3)
    print(‘%s stop play game%s‘ % (name,time.ctime()))
if __name__ == ‘__main__‘:
    # threadl = []
    # t1 = threading.Thread(target=music,args=(‘zhang‘,))
    # t2 = threading.Thread(target=game,args=(‘zhang‘,))
    # t1.start()
    # t2.start()
    music(‘zhang‘)
    game(‘zhang‘)
    print(‘Ending now %s‘%time.ctime())

場景二:主線程等待某子線程結束後才能執行(join()函數的用法)
例如:在實際中,需要子線程在插入數據,主線程需要等待數據插入結束後才能進行查詢驗證操作(測試驗證數據)
技術分享圖片
該部分代碼塊為:

import threading
import time
def music(name):
    print(‘%s begin listen music%s‘%(name,time.ctime()))
    time.sleep(5)
    print(‘%s stop listen music%s‘ % (name, time.ctime()))
def game(name):
    print(‘%s begin play game%s‘%(name,time.ctime()))
    time.sleep(3)
    print(‘%s stop play game%s‘ % (name,time.ctime()))
if __name__ == ‘__main__‘:
    threadl = []    #線程列表,用例存放線程
    #產生線程的實例
    t1 = threading.Thread(target=music,args=(‘zhang‘,)) #target是要執行的函數名(不是函數),args是函數對應的參數,以元組的形式;
    t2 = threading.Thread(target=game,args=(‘zhang‘,))
    threadl.append(t1)
    threadl.append(t2)
    #循環列表,依次執行各個子線程
    for x in threadl:
        x.start()
    #將最後一個子線程阻塞主線程,只有當該子線程完成後主線程才能往下執行
    x.join()
    print(‘Ending now %s‘%time.ctime())

該部分代碼塊為:

import threading
import time
def music(name):
    print(‘%s begin listen music%s‘%(name,time.ctime()))
    time.sleep(2)
    print(‘%s stop listen music%s‘ % (name, time.ctime()))
def game(name):
    print(‘%s begin play game%s‘%(name,time.ctime()))
    time.sleep(5)
    print(‘%s stop play game%s‘ % (name,time.ctime()))
if __name__ == ‘__main__‘:
    threadl = []    #線程列表,用例存放線程
    #產生線程的實例
    t1 = threading.Thread(target=music,args=(‘zhang‘,)) #target是要執行的函數名(不是函數),args是函數對應的參數,以元組的形式;
    t2 = threading.Thread(target=game,args=(‘zhang‘,))
    threadl.append(t1)
    threadl.append(t2)
    #循環列表,依次執行各個子線程
    for x in threadl:
        x.start()
    #將子線程t1阻塞主線程,只有當該子線程完成後主線程才能往下執行
    t1.join()
    print(‘Ending now %s‘%time.ctime())

六、線程守護(setDaemon()函數)
前面不管是不是用到了join()函數,主線程最後總是要得所有的子線程執行完成後且自己執行完才能關閉(以子線程為主來結束主線程)。下面,我們講述一種以主線程為主的方法來結束主線程。
圖1:無線程守護
技術分享圖片
圖2:t2線程守護
技術分享圖片
該部分代碼塊為:

import threading
import time
def music(name):
    print(‘%s begin listen music%s‘%(name,time.ctime()))
    time.sleep(2)
    print(‘%s stop listen music%s‘ % (name, time.ctime()))
def game(name):
    print(‘%s begin play game%s‘%(name,time.ctime()))
    time.sleep(5)
    print(‘%s stop play game%s‘ % (name,time.ctime()))
if __name__ == ‘__main__‘:
    threadl = []    #線程列表,用例存放線程
    #產生線程的實例
    t1 = threading.Thread(target=music,args=(‘zhang‘,)) #target是要執行的函數名(不是函數),args是函數對應的參數,以元組的形式;
    t2 = threading.Thread(target=game,args=(‘zhang‘,))
    threadl.append(t1)
    threadl.append(t2)
    #循環列表,依次執行各個子線程
    t2.setDaemon(True) #t2線程守護
    for x in threadl:
        x.start()
    #將子線程t1阻塞主線程,只有當該子線程完成後主線程才能往下執行
    print(‘Ending now %s‘%time.ctime())

所謂’線程守護’,就是主線程不管該線程的執行情況,只要是其他子線程結束且主線程執行完畢,主線程都會關閉。也就是說:主線程不等待該守護線程的執行完再去關閉。
註意:setDaemon方法必須在start之前且要帶一個必填的布爾型參數
七、自定義的方式來產生多線程
技術分享圖片
該部分代碼塊為:

import threading
import time
class mythread1(threading.Thread):
    ‘自定義線程‘
    def __init__(self,name):
        threading.Thread.__init__(self)
        self.name=name
    def run(self):
        ‘定義每個線程要運行的函數,此處為music函數‘
        print(‘%s begin listen music, %s‘ % (self.name, time.ctime()))
        time.sleep(5)
        print(‘%s stop listen music, %s‘ % (self.name, time.ctime()))

class mythread2(threading.Thread):
    ‘自定義線程‘
    def __init__(self,name):
        threading.Thread.__init__(self)
        self.name=name
    def run(self):
        ‘定義每個線程要運行的函數,此處為game函數‘
        print(‘%s begin play game, %s‘ % (self.name, time.ctime()))
        time.sleep(2)
        print(‘%s stop play game, %s‘ % (self.name, time.ctime()))
if __name__ == ‘__main__‘:
    threadl = []
    t1 = mythread1(‘zhang‘)
    t2 = mythread2(‘zhang‘)
    threadl.append(t1)
    threadl.append(t2)
    for x in threadl:
        x.start()
    print(‘Ending now %s‘ % time.ctime())

八、Threading的其他常用方法
getName() :獲取線程名稱
setName():設置線程名稱
run():用以表示線程活動的方法(見七中自定義線程的run方法)
rtart():啟動線程活動
is_alive():表示線程是否處於活動的狀態,結果為布爾值;
threading.active_count():返回正在運行線程的數量
Threading.enumerate():返回正在運行線程的列表
技術分享圖片
該部分代碼塊為;

import threading
import time
def music(name):
    print(‘%s begin listen music%s‘%(name,time.ctime()))
    time.sleep(2)
    print(‘%s stop listen music%s‘ % (name, time.ctime()))
def game(name):
    print(‘%s begin play game%s‘%(name,time.ctime()))
    time.sleep(5)
    print(‘%s stop play game%s‘ % (name,time.ctime()))
if __name__ == ‘__main__‘:
    threadl = []    #線程列表,用例存放線程
    #產生線程的實例
    t1 = threading.Thread(target=music,args=(‘zhang‘,)) #target是要執行的函數名(不是函數),args是函數對應的參數,以元組的形式;
    t2 = threading.Thread(target=game,args=(‘zhang‘,))
    threadl.append(t1)
    threadl.append(t2)
    #循環列表,依次執行各個子線程
    t2.setDaemon(True) #t2線程守護,setDaemon方法必須在start之前且要帶一個必填的布爾型參數
    t1.setName(‘線程1‘)   #設置線程的名字
    for x in threadl:
        print(‘線程為:‘,x.getName())   #獲取線程的名字
        print(‘線程t1是否活動:‘,t1.is_alive())    #判斷線t1是否處於活動狀態
        x.start()
    print(‘正在運行線程的數量為:‘,threading.active_count())   #獲取正處於活動狀態線程的數量
    print(‘正在運行線程的數量為:‘,threading.activeCount)       #獲取正處於活動狀態線程的數量
    print(‘正在運行線程的list為:‘,threading.enumerate())     #獲取正處於活動狀態線程的list
    print(‘正在運行線程的list為:‘,threading._enumerate())   #獲取正處於活動狀態線程的list
    #將子線程t1阻塞主線程,只有當該子線程完成後主線程才能往下執行
    print(‘正在運行的線程為:‘,threading.current_thread().getName()) #獲取當前線程的名字
    print(‘Ending now %s‘%time.ctime())

九、進程鎖

python進程和線程