欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解python如何優(yōu)雅地關(guān)閉線程

 更新時(shí)間:2024年03月27日 11:08:32   作者:__彎弓__  
這篇文章主要介紹了python如何優(yōu)雅地關(guān)閉線程,在并發(fā)編程中,我們可能會(huì)創(chuàng)建新線程,并在其中運(yùn)行任務(wù),可能由于一些原因,決定停止該線程,那么應(yīng)該如何正確關(guān)閉線程呢?文中給了詳細(xì)的解決方法,需要的朋友可以參考下

在并發(fā)編程中,我們可能會(huì)創(chuàng)建新線程,并在其中運(yùn)行任務(wù),可能由于一些原因,決定停止該線程。例如:

  • 不再需要線程任務(wù)的結(jié)果了。
  • 應(yīng)用程序正在關(guān)閉。
  • 線程執(zhí)行可能已經(jīng)出現(xiàn)了異常

Threading 模塊的 Thread 類(lèi)并沒(méi)有提供關(guān)閉線程的方法。如果不正確關(guān)閉子線程,可能遇到如下問(wèn)題:

  • 中止主線程后,子線程仍然在運(yùn)行,成為僵尸進(jìn)程
  • 子線程打開(kāi)的文件未能正確關(guān)閉,造成數(shù)據(jù)丟失
  • 子線程打開(kāi)的數(shù)據(jù)庫(kù),未能提交更新,造成數(shù)據(jù)丟失

那么應(yīng)該如何正確關(guān)閉線程呢?

1. Python 默認(rèn)關(guān)閉線程的方式

線程對(duì)象創(chuàng)建后,調(diào)用start(方法運(yùn)行, 執(zhí)行結(jié)束后,自動(dòng)關(guān)閉。如下面的示例代碼:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import threading    #導(dǎo)入threading 模塊
import time

# 定義任務(wù)函數(shù) print_time
def print_time ( threadName ,delay ):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("%s: %s \n" % (threadName,time.ctime(time.time())))

# 定義任務(wù)函數(shù) print_cube
def print_cube(num):
    #pring cube
    print("Cube:{} \n".format(num*num*num))
 
# 創(chuàng)建兩個(gè)線程
if __name__ == "__main__":
        # 創(chuàng)建兩個(gè)子線程
        t1 = threading.Thread( target=print_cube,args=(10,))
        t2 = threading.Thread( target=print_time,args=("Thread-2",4,))
        #start threads
        t1.start()   # start 后,子線程開(kāi)始運(yùn)行
        t2.start()
        t1.join()     #join 命令:讓主線程暫停運(yùn)行,等待子線程運(yùn)行結(jié)束。
        t2.join()
        print("Done") # The statement is executed after sub threads done

2. 如何優(yōu)雅地關(guān)閉線程?

上節(jié)的例子,線程執(zhí)行時(shí)間短,很快可以結(jié)束,所以主線程可以等待其結(jié)束。但是如果子線程執(zhí)行的是1個(gè)耗時(shí)任務(wù),如提供1個(gè)服務(wù),或執(zhí)行1個(gè)Monitor 任務(wù),子線程內(nèi)可能存在永久循環(huán),這時(shí)子線程對(duì)象運(yùn)行start()后,就一直處理運(yùn)行狀態(tài)。

在WIndows系統(tǒng),如果應(yīng)用程序直接退出,子線程自然也被強(qiáng)行中止,但子線程正在執(zhí)行的任務(wù)可能會(huì)受影響,如正在存取的文件可能正確關(guān)閉,造成數(shù)據(jù)丟失等。
在Linux系統(tǒng),如果應(yīng)用程序直接退出,如使用kill命令殺死進(jìn)程,未正確關(guān)閉的子線程可能仍在運(yùn)行,成為僵尸進(jìn)程。

那么如何優(yōu)雅地停止子線程呢?思路有兩個(gè):

1) 通過(guò)設(shè)置全局狀態(tài)變量來(lái)關(guān)閉線程

2) 通過(guò) threading.Event 對(duì)象來(lái)關(guān)閉線程

下面示例展示兩種方法的實(shí)現(xiàn)過(guò)程

2.1. 使用全局變量來(lái)關(guān)閉線程

實(shí)現(xiàn)步驟:

  • 在線程內(nèi)添加狀態(tài)變量
  • 線程循環(huán)體內(nèi),檢測(cè)狀態(tài)變量,如果為False ,退出循環(huán)。
  • 主線程需要關(guān)閉線程時(shí),將子線程對(duì)象的狀態(tài)變量置為False即可。

2.1.1 關(guān)閉 thread類(lèi)實(shí)現(xiàn)的線程

class CountdownTask:
      
    def __init__(self):
          self._running = True   # 定義線程狀態(tài)變量
      
	def terminate(self):
	    self._running = False 
	      
	def run(self, n):
	    # run方法的主循環(huán)條件加入對(duì)狀態(tài)變量的判斷
	    while self._running and n > 0:
	        print('T-minus', n)
	        n -= 1
	        time.sleep(5)
	    print("thread is ended") 
  
c = CountdownTask()
th = Thread(target = c.run, args =(10, ))
th.start()
# 對(duì)于耗時(shí)線程,沒(méi)必要再用join()方法了,注意主線程通常也需要有個(gè)監(jiān)控循環(huán)
# … any code … 
# Signal termination
q = input("please press any key to quit ")
c.terminate() 

2.1.2 關(guān)閉函數(shù)式線程

關(guān)閉函數(shù)式線程,可以用全局變量做狀態(tài)變量

import threading
import time
 
def run():
    while True:
        print('thread running')
        global stop_threads
        if stop_threads:
            break
 
stop_threads = False
t1 = threading.Thread(target = run)
t1.start()
time.sleep(1)
stop_threads = True
t1.join()
print('thread killed')


2.2. 使用 threading.Event 對(duì)象關(guān)閉子線程

2.2.1 Event 機(jī)制工作原理

Event 是線程間通信的一種方式。其作用相當(dāng)于1個(gè)全局flag,主線程通過(guò)控制 event 對(duì)象狀態(tài),來(lái)協(xié)調(diào)子線程步調(diào)。

使用方式

  1. 主線程創(chuàng)建 event 對(duì)象,并將其做為參數(shù)傳給子線程
  2. 主線程可以用set()方法將event 對(duì)象置為true, 用clear()方法將其置為false。
  3. 子線程循環(huán)體內(nèi),檢查 event 對(duì)象的值,如果為 True, 則退出循環(huán)。
  4. 子線程,可使用 event.wait() 將阻塞當(dāng)前子進(jìn)程,直至event 對(duì)象被置為true.

event 類(lèi)的常用方法

  • set() 設(shè)置 True
  • clear() 設(shè)置 False,
  • wait() 使進(jìn)程等待,直到flag被改為true.
  • is_set() 查詢 event 對(duì)象,如被設(shè)置為真,則返回True, 否則返回False.
if event.is_set():
     # do something before end worker 
     break

這種方式的優(yōu)點(diǎn)是,Event對(duì)象是線程安全的,而且速度更快,推薦使用這種方式關(guān)閉耗時(shí)線程。

2.2.2 完整代碼:

from time import sleep
from threading import Thread
from threading import Event
 
# define task function
def task(event):
    # execute a task in a loop
    for i in range(100):
        # block for a moment
        sleep(1)
        # check for stop
        if event.is_set():
            # 在此添加退出前要做的工作,如保存文件等
            break
        # report a message
        print('Worker thread running...')
    print('Worker is ended')
 
# create the event
event = Event()
# create a thread 
thread = Thread(target=task, args=(event,))
# start the new thread
thread.start()
# block for a while
sleep(3)
# stop the worker thread
print('Main stopping thread')
event.set()
# 這里是為了演示,實(shí)際開(kāi)發(fā)時(shí),主進(jìn)程有事件循環(huán),耗時(shí)函數(shù)不需要調(diào)用join()方法
thread.join()

子線程執(zhí)行其任務(wù)循環(huán),它每次循環(huán)都會(huì)檢查event對(duì)象,該對(duì)象保持 false,就不會(huì)觸發(fā)線程停止。

當(dāng)主線程調(diào)用event對(duì)象的 set() 方法后,在子線程循環(huán)體內(nèi),調(diào)用event對(duì)象is_set()方法,發(fā)現(xiàn)event 對(duì)象為T(mén)rue后, 立即退出任務(wù)循環(huán),結(jié)束運(yùn)行。

到此這篇關(guān)于詳解python如何優(yōu)雅地關(guān)閉線程的文章就介紹到這了,更多相關(guān)python關(guān)閉線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python計(jì)算Content-MD5并獲取文件的Content-MD5值方式

    python計(jì)算Content-MD5并獲取文件的Content-MD5值方式

    這篇文章主要介紹了python計(jì)算Content-MD5并獲取文件的Content-MD5值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • python中的正斜杠與反斜杠實(shí)例驗(yàn)證

    python中的正斜杠與反斜杠實(shí)例驗(yàn)證

    這篇文章主要介紹了python中的正斜杠與反斜杠實(shí)例驗(yàn)證,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 教你用Python寫(xiě)安卓游戲外掛

    教你用Python寫(xiě)安卓游戲外掛

    本篇文章主要給教給大家如何用python這個(gè)語(yǔ)言寫(xiě)出安卓游戲的輔助外掛以及思路講解,有興趣的朋友跟著學(xué)習(xí)下吧。
    2018-01-01
  • python指定路徑斜杠與反斜杠遇到的問(wèn)題

    python指定路徑斜杠與反斜杠遇到的問(wèn)題

    這篇文章主要介紹了python指定路徑斜杠與反斜杠遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 使用Python自定義創(chuàng)建的Log日志模塊

    使用Python自定義創(chuàng)建的Log日志模塊

    這篇文章主要介紹了使用Python自定義創(chuàng)建的Log日志模塊,日志文件是用于記錄系統(tǒng)操作事件的文件集合,可分為事件日志和消息日志。具有處理歷史數(shù)據(jù)、診斷問(wèn)題的追蹤以及理解系統(tǒng)的活動(dòng)等重要作用,需要的朋友可以參考下
    2023-07-07
  • Python性能調(diào)優(yōu)的十個(gè)小技巧總結(jié)

    Python性能調(diào)優(yōu)的十個(gè)小技巧總結(jié)

    大家好,今天這篇文章關(guān)于Python性能調(diào)優(yōu)的10個(gè)小技巧,每天花5-10分鐘閱讀我的文章,對(duì)你技術(shù)提升一定會(huì)有幫助。喜歡記得收藏以防迷路
    2021-11-11
  • numpy中hstack vstack stack concatenate函數(shù)示例詳解

    numpy中hstack vstack stack concatenate函數(shù)示例詳解

    這篇文章主要為大家介紹了numpy中hstack vstack stack concatenate函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 教你編譯pjsip源碼的方法

    教你編譯pjsip源碼的方法

    通過(guò)本文教大家如何編譯pjsip源碼,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-10-10
  • python捕獲警告的三種方法

    python捕獲警告的三種方法

    這篇文章主要介紹了python捕獲警告的三種方法,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • Python-re中search()函數(shù)的用法詳解(查找ip)

    Python-re中search()函數(shù)的用法詳解(查找ip)

    這篇文章主要介紹了Python-re中search()函數(shù)的用法-----查找ip,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論