最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中線程threading.Thread的使用詳解

 更新時間:2022年07月01日 08:46:26   作者:進擊的程小白  
python的thread模塊是比較底層的模塊,python的threading模塊是對thread做了一些包裝的,可以更加方便的被使用。本文將為大家詳細介紹一下python中的線程threading.Thread()的使用,需要的可以參考一下

1. 線程的概念

線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統(tǒng)獨立調度和分派的基本單位,線程自己不擁有系統(tǒng)資源。

2. threading.thread()的簡單使用

2.1 添加線程可以是程序運行更快

python的thread模塊是比較底層的模塊,python的threading模塊是對thread做了一些包裝的,可以更加方便的被使用

有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源

import threading
import time
 
def saySorry():
  print("親愛的,我錯了,我能吃飯了嗎?")
  time.sleep(5)
 
if __name__ == "__main__":
    start_time1 = time.time()
    for i in range(5):
      t = threading.Thread(target=saySorry)
      t.start() #啟動線程,即讓線程開始執(zhí)行
    end_time1 = time.time()
    print(end_time1 - start_time1)
 
    start_time2 = time.time()
    for i in range(5):
        t = saySorry()
 
    end_time2 = time.time()
    print(end_time2 - start_time2)

輸出為:

親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
0.001995086669921875
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
親愛的,我錯了,我能吃飯了嗎?
25.001766204833984

2.2 主線程會等待所有的子線程結束后才結束

import threading
from time import sleep,ctime
 
def sing():
  for i in range(3):
    print("正在唱歌...%d"%i)
    sleep(1)
 
def dance():
  for i in range(3):
    print("正在跳舞...%d"%i)
    sleep(1)
 
if __name__ == '__main__':
  print('---開始---:%s'%ctime())
 
  t1 = threading.Thread(target=sing)
  t2 = threading.Thread(target=dance)
 
  t1.start()
  t2.start()
 
  # sleep(5) # 屏蔽此行代碼,試試看,程序是否會立馬結束?
  print('---結束---:%s'%ctime())

輸出為:

---開始---:Mon Sep 28 14:42:09 2020
正在唱歌...0
正在跳舞...0---結束---:Mon Sep 28 14:42:09 2020
 
正在唱歌...1
正在跳舞...1
正在唱歌...2
正在跳舞...2

如果釋放‘ sleep(5) ’,輸出為:

---開始---:Mon Sep 28 14:43:36 2020
正在唱歌...0
正在跳舞...0
正在跳舞...1
正在唱歌...1
正在唱歌...2正在跳舞...2
 
---結束---:Mon Sep 28 14:43:41 2020

3.查看線程數量

import threading
from time import sleep,ctime
 
def sing():
  for i in range(3):
    print("正在唱歌...%d"%i)
    sleep(1)
 
def dance():
  for i in range(3):
    print("正在跳舞...%d"%i)
    sleep(1)
 
if __name__ == '__main__':
  print('---開始---:%s'%ctime())
 
  t1 = threading.Thread(target=sing)
  t2 = threading.Thread(target=dance)
 
  t1.start()
  t2.start()
 
  while True:
    length = len(threading.enumerate())
    print('當前運行的線程數為:%d'%length)
    if length<=1:
      break
 
    sleep(0.5)

輸出為:

---開始---:Mon Sep 28 14:46:16 2020
正在唱歌...0
正在跳舞...0
當前運行的線程數為:3
當前運行的線程數為:3
正在唱歌...1
正在跳舞...1當前運行的線程數為:3
 
當前運行的線程數為:3
正在唱歌...2
正在跳舞...2
當前運行的線程數為:3
當前運行的線程數為:3
當前運行的線程數為:1

4.線程參數及順序

4.1 傳遞參數的方法

使用args 傳遞參數 threading.Thread(target=sing, args=(10, 100, 100))

使用kwargs傳遞參數 threading.Thread(target=sing, kwargs={“a”: 10, “b”:100, “c”: 100})

同時使用 args 和 kwargs 傳遞參數 threading.Thread(target=sing, args=(10, ), kwargs={“b”: 100,“c”: 100})

4.2 線程的執(zhí)行順序

import threading
import time
 
 
def sing():
    for i in range(5):
        print("我是sing")
        time.sleep(1)
 
 
def dance():
    for i in range(5):
        print("我是dance")
        time.sleep(1)
 
 
if __name__ == '__main__':
    # 創(chuàng)建兩個子線程
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    # 啟動子線程
    t1.start()
    t2.start()

輸出為:

我是sing
我是dance
我是sing
我是dance
我是dance
我是sing
我是dance我是sing
 
我是sing
我是dance

說明:

從代碼和執(zhí)行結果我們可以看出,多線程程序的執(zhí)行順序是不確定的。當執(zhí)行到sleep語句時,線程將被阻塞(Blocked),到sleep結束后,線程進入就緒(Runnable)狀態(tài),等待調度。而線程調度將自行選擇一個線程執(zhí)行。上面的代碼中只能保證每個線程都運行完整個run函數,但是線程的啟動順序、run函數中每次循環(huán)的執(zhí)行順序都不能確定。

5. 守護線程

守護線程:如果在程序中將子線程設置為守護線程,則該子線程會在主線程結束時自動退出,設置方式為thread.setDaemon(True),要在thread.start()之前設置,默認是false的,也就是主線程結束時,子線程依然在執(zhí)行。

5.1 如下代碼,主線程已經exit() 【其實并沒有真正結束】,子線程還在繼續(xù)執(zhí)行

import threading
import time
 
def test():
  for i in range(7):
    print("test is run:", i)
    time.sleep(1)
 
if __name__ == '__main__':
  # 創(chuàng)建子線程
  t1 = threading.Thread(target=test)
  # 啟動子線程
  t1.start()
  # 休眠2秒
  time.sleep(2)
 
  print("我 OVER 了")
  # 退出
  exit()

輸出為:

test is run: 0
test is run: 1
我 OVER 了
test is run: 2
test is run: 3
test is run: 4
test is run: 5
test is run: 6

5.2 設置守護線程

為線程設置守護,如果主線程結束,子線程也隨之結束。

import threading
import time
 
def test():
  for i in range(7):
    print("test is run:", i)
    time.sleep(1)
 
if __name__ == '__main__':
  # 創(chuàng)建子線程
  t1 = threading.Thread(target=test)
  #設置線程保護
  t1.setDaemon(True)
  # 啟動子線程
  t1.start()
  # 休眠2秒
  time.sleep(2)
 
  print("我 OVER 了")
  # 退出
  exit()

輸出為:

test is run: 0
test is run: 1
我 OVER 了

參考代碼

import threading
from threading import Lock,Thread
import time,os
 
 
'''
                                      python多線程詳解
      什么是線程?
      線程也叫輕量級進程,是操作系統(tǒng)能夠進行運算調度的最小單位,它被包涵在進程之中,是進程中的實際運作單位。
      線程自己不擁有系統(tǒng)資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其他線程共享進程所
      擁有的全部資源。一個線程可以創(chuàng)建和撤銷另一個線程,同一個進程中的多個線程之間可以并發(fā)執(zhí)行
'''
 
'''
    為什么要使用多線程?
    線程在程序中是獨立的、并發(fā)的執(zhí)行流。與分隔的進程相比,進程中線程之間的隔離程度要小,它們共享內存、文件句柄
    和其他進程應有的狀態(tài)。
    因為線程的劃分尺度小于進程,使得多線程程序的并發(fā)性高。進程在執(zhí)行過程之中擁有獨立的內存單元,而多個線程共享
    內存,從而極大的提升了程序的運行效率。
    線程比進程具有更高的性能,這是由于同一個進程中的線程都有共性,多個線程共享一個進程的虛擬空間。線程的共享環(huán)境
    包括進程代碼段、進程的共有數據等,利用這些共享的數據,線程之間很容易實現通信。
    操作系統(tǒng)在創(chuàng)建進程時,必須為改進程分配獨立的內存空間,并分配大量的相關資源,但創(chuàng)建線程則簡單得多。因此,使用多線程
    來實現并發(fā)比使用多進程的性能高得要多。
'''
 
'''
    總結起來,使用多線程編程具有如下幾個優(yōu)點:
    進程之間不能共享內存,但線程之間共享內存非常容易。
    操作系統(tǒng)在創(chuàng)建進程時,需要為該進程重新分配系統(tǒng)資源,但創(chuàng)建線程的代價則小得多。因此使用多線程來實現多任務并發(fā)執(zhí)行比使用多進程的效率高
    python語言內置了多線程功能支持,而不是單純地作為底層操作系統(tǒng)的調度方式,從而簡化了python的多線程編程。
'''
 
 
'''
    普通創(chuàng)建方式
'''
# def run(n):
#     print('task',n)
#     time.sleep(1)
#     print('2s')
#     time.sleep(1)
#     print('1s')
#     time.sleep(1)
#     print('0s')
#     time.sleep(1)
#
# if __name__ == '__main__':
#     t1 = threading.Thread(target=run,args=('t1',))     # target是要執(zhí)行的函數名(不是函數),args是函數對應的參數,以元組的形式存在
#     t2 = threading.Thread(target=run,args=('t2',))
#     t1.start()
#     t2.start()
 
 
'''
    自定義線程:繼承threading.Thread來定義線程類,其本質是重構Thread類中的run方法
'''
# class MyThread(threading.Thread):
#     def __init__(self,n):
#         super(MyThread,self).__init__()   #重構run函數必須寫
#         self.n = n
#
#     def run(self):
#         print('task',self.n)
#         time.sleep(1)
#         print('2s')
#         time.sleep(1)
#         print('1s')
#         time.sleep(1)
#         print('0s')
#         time.sleep(1)
#
# if __name__ == '__main__':
#     t1 = MyThread('t1')
#     t2 = MyThread('t2')
#     t1.start()
#     t2.start()
 
 
'''
    守護線程
    下面這個例子,這里使用setDaemon(True)把所有的子線程都變成了主線程的守護線程,
    因此當主線程結束后,子線程也會隨之結束,所以當主線程結束后,整個程序就退出了。
    所謂'線程守護',就是主線程不管該線程的執(zhí)行情況,只要是其他子線程結束且主線程執(zhí)行完畢,主線程都會關閉。也就是說:主線程不等待該守護線程的執(zhí)行完再去關閉。
'''
# def run(n):
#     print('task',n)
#     time.sleep(1)
#     print('3s')
#     time.sleep(1)
#     print('2s')
#     time.sleep(1)
#     print('1s')
#
# if __name__ == '__main__':
#     t=threading.Thread(target=run,args=('t1',))
#     t.setDaemon(True)
#     t.start()
#     print('end')
'''
    通過執(zhí)行結果可以看出,設置守護線程之后,當主線程結束時,子線程也將立即結束,不再執(zhí)行
'''
 
'''
    主線程等待子線程結束
    為了讓守護線程執(zhí)行結束之后,主線程再結束,我們可以使用join方法,讓主線程等待子線程執(zhí)行
'''
# def run(n):
#     print('task',n)
#     time.sleep(2)
#     print('5s')
#     time.sleep(2)
#     print('3s')
#     time.sleep(2)
#     print('1s')
# if __name__ == '__main__':
#     t=threading.Thread(target=run,args=('t1',))
#     t.setDaemon(True)    #把子線程設置為守護線程,必須在start()之前設置
#     t.start()
#     t.join()     #設置主線程等待子線程結束
#     print('end')
 
 
'''
    多線程共享全局變量
    線程時進程的執(zhí)行單元,進程時系統(tǒng)分配資源的最小執(zhí)行單位,所以在同一個進程中的多線程是共享資源的
'''
# g_num = 100
# def work1():
#     global  g_num
#     for i in range(3):
#         g_num+=1
#     print('in work1 g_num is : %d' % g_num)
#
# def work2():
#     global g_num
#     print('in work2 g_num is : %d' % g_num)
#
# if __name__ == '__main__':
#     t1 = threading.Thread(target=work1)
#     t1.start()
#     time.sleep(1)
#     t2=threading.Thread(target=work2)
#     t2.start()
 
 
'''
        由于線程之間是進行隨機調度,并且每個線程可能只執(zhí)行n條執(zhí)行之后,當多個線程同時修改同一條數據時可能會出現臟數據,
    所以出現了線程鎖,即同一時刻允許一個線程執(zhí)行操作。線程鎖用于鎖定資源,可以定義多個鎖,像下面的代碼,當需要獨占
    某一個資源時,任何一個鎖都可以鎖定這個資源,就好比你用不同的鎖都可以把這個相同的門鎖住一樣。
        由于線程之間是進行隨機調度的,如果有多個線程同時操作一個對象,如果沒有很好地保護該對象,會造成程序結果的不可預期,
    我們因此也稱為“線程不安全”。
        為了防止上面情況的發(fā)生,就出現了互斥鎖(Lock)
'''
# def work():
#     global n
#     lock.acquire()
#     temp = n
#     time.sleep(0.1)
#     n = temp-1
#     lock.release()
#
#
# if __name__ == '__main__':
#     lock = Lock()
#     n = 100
#     l = []
#     for i in range(100):
#         p = Thread(target=work)
#         l.append(p)
#         p.start()
#     for p in l:
#         p.join()
 
 
'''
    遞歸鎖:RLcok類的用法和Lock類一模一樣,但它支持嵌套,在多個鎖沒有釋放的時候一般會使用RLock類
'''
# def func(lock):
#     global gl_num
#     lock.acquire()
#     gl_num += 1
#     time.sleep(1)
#     print(gl_num)
#     lock.release()
#
#
# if __name__ == '__main__':
#     gl_num = 0
#     lock = threading.RLock()
#     for i in range(10):
#         t = threading.Thread(target=func,args=(lock,))
#         t.start()
 
 
'''
    信號量(BoundedSemaphore類)
    互斥鎖同時只允許一個線程更改數據,而Semaphore是同時允許一定數量的線程更改數據,比如廁所有3個坑,
    那最多只允許3個人上廁所,后面的人只能等里面有人出來了才能再進去
'''
# def run(n,semaphore):
#     semaphore.acquire()   #加鎖
#     time.sleep(3)
#     print('run the thread:%s\n' % n)
#     semaphore.release()    #釋放
#
#
# if __name__== '__main__':
#     num=0
#     semaphore = threading.BoundedSemaphore(5)   #最多允許5個線程同時運行
#     for i in range(22):
#         t = threading.Thread(target=run,args=('t-%s' % i,semaphore))
#         t.start()
#     while threading.active_count() !=1:
#         pass
#     else:
#         print('----------all threads done-----------')
 
'''
    python線程的事件用于主線程控制其他線程的執(zhí)行,事件是一個簡單的線程同步對象,其主要提供以下的幾個方法:
        clear將flag設置為 False
        set將flag設置為 True
        is_set判斷是否設置了flag
        wait會一直監(jiān)聽flag,如果沒有檢測到flag就一直處于阻塞狀態(tài)
    事件處理的機制:全局定義了一個Flag,當Flag的值為False,那么event.wait()就會阻塞,當flag值為True,
    那么event.wait()便不再阻塞
'''
event = threading.Event()
def lighter():
    count = 0
    event.set()         #初始者為綠燈
    while True:
        if 5 < count <=10:
            event.clear()  #紅燈,清除標志位
            print("\33[41;lmred light is on...\033[0m]")
        elif count > 10:
            event.set()    #綠燈,設置標志位
            count = 0
        else:
            print('\33[42;lmgreen light is on...\033[0m')
 
        time.sleep(1)
        count += 1
 
 
def car(name):
    while True:
        if event.is_set():     #判斷是否設置了標志位
            print('[%s] running.....'%name)
            time.sleep(1)
        else:
            print('[%s] sees red light,waiting...'%name)
            event.wait()
            print('[%s] green light is on,start going...'%name)
 
 
# startTime = time.time()
light = threading.Thread(target=lighter,)
light.start()
 
car = threading.Thread(target=car,args=('MINT',))
car.start()
endTime = time.time()
# print('用時:',endTime-startTime)
 
'''
                           GIL  全局解釋器
        在非python環(huán)境中,單核情況下,同時只能有一個任務執(zhí)行。多核時可以支持多個線程同時執(zhí)行。但是在python中,無論有多少個核
        同時只能執(zhí)行一個線程。究其原因,這就是由于GIL的存在導致的。
        GIL的全程是全局解釋器,來源是python設計之初的考慮,為了數據安全所做的決定。某個線程想要執(zhí)行,必須先拿到GIL,我們可以
        把GIL看做是“通行證”,并且在一個python進程之中,GIL只有一個。拿不到線程的通行證,并且在一個python進程中,GIL只有一個,
        拿不到通行證的線程,就不允許進入CPU執(zhí)行。GIL只在cpython中才有,因為cpython調用的是c語言的原生線程,所以他不能直接操
        作cpu,而只能利用GIL保證同一時間只能有一個線程拿到數據。而在pypy和jpython中是沒有GIL的
        python在使用多線程的時候,調用的是c語言的原生過程。
'''
'''
                            python針對不同類型的代碼執(zhí)行效率也是不同的
        1、CPU密集型代碼(各種循環(huán)處理、計算等),在這種情況下,由于計算工作多,ticks技術很快就會達到閥值,然后出發(fā)GIL的
        釋放與再競爭(多個線程來回切換當然是需要消耗資源的),所以python下的多線程對CPU密集型代碼并不友好。
        2、IO密集型代碼(文件處理、網絡爬蟲等設計文件讀寫操作),多線程能夠有效提升效率(單線程下有IO操作會進行IO等待,
        造成不必要的時間浪費,而開啟多線程能在線程A等待時,自動切換到線程B,可以不浪費CPU的資源,從而能提升程序的執(zhí)行
        效率)。所以python的多線程對IO密集型代碼比較友好。
'''
'''
    主要要看任務的類型,我們把任務分為I/O密集型和計算密集型,而多線程在切換中又分為I/O切換和時間切換。如果任務屬于是I/O密集型,
    若不采用多線程,我們在進行I/O操作時,勢必要等待前面一個I/O任務完成后面的I/O任務才能進行,在這個等待的過程中,CPU處于等待
    狀態(tài),這時如果采用多線程的話,剛好可以切換到進行另一個I/O任務。這樣就剛好可以充分利用CPU避免CPU處于閑置狀態(tài),提高效率。但是
    如果多線程任務都是計算型,CPU會一直在進行工作,直到一定的時間后采取多線程時間切換的方式進行切換線程,此時CPU一直處于工作狀態(tài),
    此種情況下并不能提高性能,相反在切換多線程任務時,可能還會造成時間和資源的浪費,導致效能下降。這就是造成上面兩種多線程結果不能的解釋。
結論:I/O密集型任務,建議采取多線程,還可以采用多進程+協(xié)程的方式(例如:爬蟲多采用多線程處理爬取的數據);對于計算密集型任務,python此時就不適用了。
'''

以上就是Python中線程threading.Thread的使用詳解的詳細內容,更多關于Python threading.Thread的資料請關注腳本之家其它相關文章!

相關文章

最新評論

民丰县| 三河市| 宜章县| 昆明市| 泸定县| 海安县| 同德县| 迁安市| 象州县| 藁城市| 梁山县| 临颍县| 泽州县| 新蔡县| 藁城市| 金川县| 井陉县| 亳州市| 红原县| 临漳县| 龙泉市| 新野县| 延川县| 尉犁县| 萍乡市| 建瓯市| 宁河县| 苗栗市| 屏南县| 新河县| 太仓市| 利津县| 柘荣县| 凌海市| 汪清县| 永嘉县| 图们市| 虎林市| 航空| 柳林县| 夏河县|