python多執行緒程式設計總結(三)

2021-06-26 16:09:26 字數 4211 閱讀 7154

一,守護程序和非守護執行緒

到目前為止,示例程式都隱含地等待所有執行緒完成工作之後才退出。程式有時會建立乙個執行緒作為守護執行緒,這個執行緒一直執行而不阻塞主程式的退出。如果乙個服務無法用一種容易的方法來中斷執行緒,或者希望執行緒工作到一半時候終止而不損失或破壞資料(如為乙個服務監控程式工具生成「心跳執行緒」)對於這些服務,使用守護執行緒就很有用,上面一段話要好好理解。要標誌乙個守護執行緒,需要使用setdaemon()方法,並提供引數true。預設情況下,所有執行緒都不是守護執行緒,包括主線程。

**如下:

import threading

import time

import logging

logging.basicconfig(

level = logging.debug,

format = '%(levelname)s (%(threadname)s) %(message)s', )

def worker():

logging.debug('starting')

time.sleep(2)

logging.debug('exiting')

d = threading.thread(target = worker,name = 'worker')

d.setdaemon(true)

def job():

logging.debug('starting')

logging.debug('exiting')

t = threading.thread(target = job,name = 'job')

d.start()

t.start()

結果如下:

debug (worker) starting

debug (job) starting

debug (job) exiting

[finished in 0.6s]

解釋:可以發現程式結束後,沒有發現woker的exiting的資訊,因為在守護執行緒從其2秒的睡眠時間喚醒之前,所有非守護執行緒已經退出(包括主線程)。有興趣的同學,可以把主線程也sleep(5),會發現執行緒woker會輸出exiting資訊。多思考。

二,要等待乙個守護執行緒完成工作,需要使用join()方法。

**如下:

import threading

import time

import logging

logging.basicconfig(

level = logging.debug,

format = '%(levelname)s (%(threadname)s) %(message)s', )

def worker():

logging.debug('starting')

time.sleep(2)

logging.debug('exiting')

d = threading.thread(target = worker,name = 'worker')

d.setdaemon(true)

def job():

logging.debug('starting')

logging.debug('exiting')

t = threading.thread(target = job,name = 'job')

d.start()

t.start()

d.join()

t.join()

結果如下:

debug (worker) starting

debug (job) starting

debug (job) exiting

debug (worker) exiting

[finished in 2.6s]

解釋:使用join()等待守護執行緒退出,這意味著它將有機會生成它的"exiting"訊息。

三,join傳入結束時間。預設情況下,join()會無限阻塞,還可以傳入乙個浮點數值,表示等待執行緒變為不活動所需的時間(秒數),即使執行緒在這個時間段內未完成,join()也會返回。

**如下:

import threading

import time

import logging

logging.basicconfig(

level = logging.debug,

format = '%(levelname)s (%(threadname)s) %(message)s', )

def worker():

logging.debug('starting')

time.sleep(2)

logging.debug('exiting')

d = threading.thread(target = worker,name = 'worker')

d.setdaemon(true)

def job():

logging.debug('starting')

logging.debug('exiting')

t = threading.thread(target = job,name = 'job')

d.start()

t.start()

d.join(1)

print 'alive?',d.isalive()

t.join()

結果如下:

debug (worker) starting

debug (job) starting

debug (job) exiting

alive? true

[finished in 1.2s]

解釋:由於傳入的時間小於守護執行緒睡眠時間,所以join返回之後,這個執行緒仍「存活」

join總結一下:

1.join方法的作用是阻塞主程序(擋住,無法執行join以後的語句),專注執行多執行緒。

2.多執行緒多join的情況下,依次執行各執行緒的join方法,前頭乙個結束了才能執行後面乙個。

3.無引數,則等待到該執行緒結束,才開始執行下乙個執行緒的join。

4.設定引數後,則等待該執行緒這麼長時間就不管它了(而該執行緒並沒有結束)。不管的意思就是可以執行後面的主程序了。

(上面這段是在網上找的,總結的很好)

四, 列舉所有執行緒

沒有必要為所有守護執行緒維護乙個顯式控制代碼來確保他們在退出主線程之前已經完成。enumerate()會返回活動的thread例項的乙個列表,這個列表頁包括當前的主線程,由於等待當前主線程結束會進入一種死鎖狀態,所以必須將其跳過。以上的這段話要說明兩點。1、使用enumerate可以顯示出所有活動執行緒。2、給守護執行緒新增控制代碼的乙個方法。

**如下:

import threading

import time

import logging

import random

logging.basicconfig(

level = logging.debug,

format = '%(levelname)s (%(threadname)s) %(message)s', )

def worker():

pause = random.randint(1,5)

logging.debug('sleep %s',pause)

time.sleep(pause)

logging.debug('ending')

for i in range(3):

t = threading.thread(target = worker)

t.setdaemon(true)

t.start()

main_thread = threading.currentthread()

for t in threading.enumerate():

if t is main_thread:    #跳過主線程,否則會出現死鎖

continue

logging.debug('joining %s',t.getname())

t.join()

解釋:注意enumerate的使用,以及需要跳出主線程

多執行緒程式設計總結

面試中問到這三個小問題 1 多執行緒主要用於什麼上?舉幾個例子 2 開啟乙個word是程序還是執行緒?開啟之後開啟了很多word檔案是執行緒還是程序?3 計算器軟體的執行時程序的還是多執行緒的?答 1 具有多執行緒能力的計算機因有硬體支援而能夠在同一時間執行多於乙個執行緒。生產者 消費者模型的滑鼠螢...

多執行緒程式設計總結

之前自己寫過乙個所謂的執行緒總結,那是剛學習的時候,想的只是怎麼建立執行緒,後來剖析原始碼的時候發現了自己在這方面知識的匱乏,於是最近痛定思痛,再去去看了一遍多執行緒程式設計。根據執行環境和排程者身份 執行緒可以分為核心執行緒和使用者執行緒。核心執行緒由核心來排程,執行在核心空間 使用者執行緒執行在...

多執行緒程式設計 三

放入資料 獲取資料 arrayblockingqueu 和 linkedblockingqueue arrayblockingqueu 是用陣列實現的有界阻塞佇列,並按照先進先出 fifo 的原則對元素進行排序。第乙個引數是容量 第二個引數是是否要保證執行緒的公平地訪問佇列 預設是false arr...