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

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

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

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

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

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

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

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

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

線程對象創(chuàng)建后,調(diào)用start(方法運行, 執(zhí)行結(jié)束后,自動關(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)建兩個線程
if __name__ == "__main__":
        # 創(chuàng)建兩個子線程
        t1 = threading.Thread( target=print_cube,args=(10,))
        t2 = threading.Thread( target=print_time,args=("Thread-2",4,))
        #start threads
        t1.start()   # start 后,子線程開始運行
        t2.start()
        t1.join()     #join 命令:讓主線程暫停運行,等待子線程運行結(jié)束。
        t2.join()
        print("Done") # The statement is executed after sub threads done

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

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

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

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

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

2) 通過 threading.Event 對象來關(guān)閉線程

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

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

實現(xiàn)步驟:

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

2.1.1 關(guān)閉 thread類實現(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)條件加入對狀態(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()
# 對于耗時線程,沒必要再用join()方法了,注意主線程通常也需要有個監(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 對象關(guān)閉子線程

2.2.1 Event 機制工作原理

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

使用方式

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

event 類的常用方法

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

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

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()
# 這里是為了演示,實際開發(fā)時,主進程有事件循環(huán),耗時函數(shù)不需要調(diào)用join()方法
thread.join()

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

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

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

相關(guān)文章

  • Python3基礎(chǔ)之函數(shù)用法

    Python3基礎(chǔ)之函數(shù)用法

    這篇文章主要介紹了Python3的函數(shù)用法,非常重要,需要的朋友可以參考下
    2014-08-08
  • 最新評論

    林州市| 隆化县| 驻马店市| 庆安县| 汨罗市| 海伦市| 普兰县| 邯郸县| 大城县| 介休市| 滨海县| 抚远县| 南和县| 商南县| 都安| 建水县| 西充县| 新津县| 富锦市| 威宁| 桂东县| 宁安市| 喀什市| 资兴市| 定兴县| 滨州市| 余江县| 洪洞县| 炎陵县| 库尔勒市| 会东县| 阜南县| 渝中区| 渑池县| 甘谷县| 漳州市| 繁峙县| 大庆市| 兰坪| 如皋市| 桦南县|