Python -- 多線程

--coding:utf-8--

2 python實現線程的方式

1.函數方式(涉及_thread模塊)
2.用類包裝線程對象(涉及threading模塊)

2.1函數方式實現多線程

1.調用_thread模塊的start_new_thread()函數創(chuàng)建并啟動新線程
語法:_thread.start_new_thread(function,args[,kwargs])
function:線程函數
args:傳遞給線程函數的參數,必須是tuple類型
kwargs:可選參數
import _thread
import time
def workThread(threadName,delay):
    print('[啟動]>>>{0}'.format(threadName))
    counter = 0 #計數器
    for i in range(delay):
        counter += 1
        time.sleep(1)
        pass
    print('[停止]>>>{0}'.format(threadName))
    pass

if __name__ == '__main__':
    _thread.start_new_thread(workThread,('thread-1',3))
    _thread.start_new_thread(workThread,('thread-2',5))
    for i in range(4):
        print('mainThread正在執(zhí)行')
        time.sleep(1)
        pass
    print('>>>主線程mainThread停止\a')
    print('-' * 50)

備注:線程結束一般依靠線程函數的自然結束蹬叭,也可在線程中調用thread.exit(),拋出SystemExit exception 達到退出線程的目的

2.2模塊實現方式

python通過兩個標準庫_thread和threading提供線程支持
_thread提供低級別的枕磁,原始的線程以及一個簡單的鎖
threading模塊提供其他方法:
1.threading.currentThread():返回當前線程變量
2.threading.enumerate():返回一個包含正在運行線程的list秦叛,正在運行線程啟動后脑蠕,結束前艺谆,不包括啟動前和終止后的線程
3.threading.activeCount():返回正在運行的線程數量棵红,與len(threading.enumerate())有相同的結果

除此之外胀糜,線程模塊提供threading.Thread類來處理線程祟昭,threading.Thread提供如下函數
1.run():表示線程活動的方法
2.start():啟動線程活動
3.join([time]):等待至線程中止缕坎,這阻塞調用線程直至線程的join()方法被調用中止-正常退出或者拋出未處理的異常-或者是可選
4.isAlive():返回線程是否是活動的
5.getName():返回線程名
6.setName():設置線程名

語法:
import threading
#創(chuàng)建線程類
class 線程類名稱(threading.Thread):

    def __init__(self,參數1,...,參數N):
        #調用父類構造方法
        threading.thread.__init__(self)
        ...
    #重寫run(),線程啟動后的調用
    def run():
        ...

線程對象 = 線程類名稱()
線程對象.run() #啟動線程
import threading
import time
exitFlag = 0 #創(chuàng)建推出標志位變量

def outputTime(threadName,delay,counter):
    while counter:
        if exitFlag:
            threading.Thread.exit()
        time.sleep(delay)
        print('%s:%s' % (threadName,time.ctime(time.time())))
        counter -= 1
        pass
    pass

class MyThread(threading.Thread):
    """docstring for MyThread"""
    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)
        outputTime(self.name,self.counter,5)
        print('結束>' + self.name)
        pass


if __name__ == '__main__':
    print('mainThread主線程啟動.....')
    thread1 = MyThread(1,'thread-11',1)
    thread2 = MyThread(2,'thread-22',1)
    thread1.run()
    thread2.run()
    print('mainThread主線程結束')

3.線程同步

線程有五個狀態(tài),狀態(tài)切換如下
      啟動          調度          結束
新建          就緒          運行          死亡
                         | 阻塞條件
                        阻塞

所線程在執(zhí)行時為隨機模式篡悟,不可控谜叹,要求執(zhí)行順序可控就得用線程同步
Python 線程同步技術的解決方案:鎖同步和條件變量同步

3.1創(chuàng)建線程鎖的語法:
線程鎖對象 = Threading.Lock
鎖定:線程鎖對象.acquire()
解除鎖定:線程鎖對象.release()

使用場景:
def run(self):
    線程鎖對象.acquire()
    ...線程執(zhí)行語句...
    線程鎖對象.release()

#3.2條件變量同步
python 提供的Condition對象提供了對復雜線程同步問題的支持
Condition被稱為條件變量,除了提供Lock類似的acquire和release方法搬葬,還提供wait和notify
工作原理:
線程首先acquire一個條件變量荷腊,然后判斷一些條件,不滿足wait,滿足進行處理改變條件后急凰,通過notify方法通知其他線程女仰,其他處于wait的線程接到通知會重新判斷條件,重復這一過程抡锈,從而解決復雜的同步問題

示例:生產者和消費者

生產者消費者問題(有限緩沖問題)疾忍,是一個多線程同步的經典案例,該問題描述兩個共享固定大小緩存的線程--即所謂的‘生產者‘和’消費者‘在實際運行時會發(fā)生的問題
生產者作用時生成一定量的數據放到緩沖區(qū)企孩,重復此過程
消費者在緩沖區(qū)消耗這些數據
該問題的【關鍵】保證生產者不會在緩沖區(qū)滿時加入數據锭碳,消費者也不會在緩沖區(qū)空時消耗數據
任務說明:
1.創(chuàng)建一個共享區(qū),容量是10
2.兩個生產者勿璃,隨機時間單位產生1件商品放入共享區(qū)擒抛,count + 1,共享區(qū)滿补疑,生產者停止放入共享區(qū)歧沪,線程進入block阻塞狀態(tài),等待消費者線程喚醒
3.五個消費者莲组,隨機時間單位產生從共享區(qū)取1件商品诊胞,count - 1,共享區(qū)空,消費者停止從共享區(qū)獲取撵孤,線程進入block阻塞狀態(tài)迈着,等待生產者線程喚醒

import threading
import time
import random #隨機模塊
#使用共享區(qū)模擬變量
count= 0 
#創(chuàng)建條件對象
condition = threading.Condition()

#生產者線程類
class Producer(threading.Thread):
    def __init__(self,threadName):
        threading.Thread.__init__(self)
        self.threadName = threadName

    def run(self):
        global count #引用全局共享變量count
        while True:
            #使用條件變量后去鎖并速定
            if condition.acquire():
                #判斷共享變量是否達到上限(已滿)
                if count >= 10:
                    print('共享區(qū)已滿,生產者Producer線程進入阻塞block狀態(tài)邪码,停止放入裕菠!')
                    #當前線程進入阻塞狀態(tài)
                    condition.wait()
                else:
                    count += 1 #共享變量自增1
                    print(time.ctime() + ' ' + self.threadName + '生產了1件商品放入共享區(qū),共享區(qū)商品總計個數:{0}'.format(count))
                    condition.notify() #喚醒其他阻塞線程
                condition.release()
                time.sleep(random.randrange(10)/5) #隨機休眠N秒


#消費者線程
class Customer(threading.Thread):
    def __init__(self, threadName):
        threading.Thread.__init__(self)
        self.threadName = threadName

    def run(self):
        global count #引用全局共享變量count
        while True:
            #使用條件變量后去鎖并速定
            if condition.acquire():
                #判斷共享變量是否達到上限(已滿)
                if count < 1:
                    print('共享區(qū)已空闭专,消費者Customer線程進入阻塞block狀態(tài)奴潘,停止獲取影钉!')
                    #當前線程進入阻塞狀態(tài)
                    condition.wait()
                else:
                    count -= 1 #共享變量自減1
                    print(time.ctime() + ' ' + self.threadName + '消費了1件商品画髓,共享區(qū)商品總計個數:' + str(count))
                    condition.notify() #喚醒其他阻塞線程
                condition.release()
                time.sleep(random.randrange(10)) #隨機休眠N秒

if __name__ == '__main__':
    for i in range(2):
        p = Producer('[生產者-' + str(i + 1) + ']')
        p.start()

    for i in range(5):
        c = Producer('[消費者-' + str(i + 1) + ']')
        c.start()

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市平委,隨后出現的幾起案子奈虾,更是在濱河造成了極大的恐慌,老刑警劉巖肆汹,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愚墓,死亡現場離奇詭異,居然都是意外死亡昂勉,警方通過查閱死者的電腦和手機浪册,發(fā)現死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岗照,“玉大人村象,你說我怎么就攤上這事≡苤粒” “怎么了厚者?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長迫吐。 經常有香客問我库菲,道長,這世上最難降的妖魔是什么志膀? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任熙宇,我火速辦了婚禮,結果婚禮上溉浙,老公的妹妹穿的比我還像新娘烫止。我一直安慰自己,他們只是感情好戳稽,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布馆蠕。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪互躬。 梳的紋絲不亂的頭發(fā)上播赁,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音吨铸,去河邊找鬼行拢。 笑死祖秒,一個胖子當著我的面吹牛诞吱,可吹牛的內容都是我干的。 我是一名探鬼主播竭缝,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼房维,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抬纸?” 一聲冷哼從身側響起咙俩,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湿故,沒想到半個月后阿趁,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡坛猪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年脖阵,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墅茉。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡命黔,死狀恐怖,靈堂內的尸體忽然破棺而出就斤,到底是詐尸還是另有隱情悍募,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布洋机,位于F島的核電站坠宴,受9級特大地震影響,放射性物質發(fā)生泄漏绷旗。R本人自食惡果不足惜喜鼓,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刁标。 院中可真熱鬧颠通,春花似錦、人聲如沸膀懈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至硼控,卻和暖如春刘陶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牢撼。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工匙隔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熏版。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓纷责,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撼短。 傳聞我的和親對象是個殘疾皇子再膳,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容

  • 一文讀懂Python多線程 1、線程和進程 計算機的核心是CPU曲横,它承擔了所有的計算任務喂柒。它就像一座工廠,時刻在運...
    星丶雲閱讀 1,453評論 0 4
  • Python 多線程 多線程類似于同時執(zhí)行多個不同程序禾嫉,多線程運行有如下優(yōu)點: 使用線程可以把占據長時間的程序...
    今早上閱讀 353評論 0 0
  • 免費Python課程:阿里云大學——開發(fā)者課堂 Python中使用線程有兩種方式:函數或者用類來包裝線程對象熙参。 函...
    開發(fā)者學習指南閱讀 206評論 0 0
  • 多線程基礎概念 并行與并發(fā) 并行:同時處理多個任務艳吠,必須在多核環(huán)境下 一段時間內同時處理多個任務,單核也可以并發(fā) ...
    職場亮哥閱讀 654評論 0 0
  • 久違的晴天尊惰,家長會讲竿。 家長大會開好到教室時,離放學已經沒多少時間了弄屡。班主任說已經安排了三個家長分享經驗题禀。 放學鈴聲...
    飄雪兒5閱讀 7,520評論 16 22