在實際應用中,我們經常需要使用定時器去觸發一些事件。Python中通過線程實現定時器timer,其使用非常簡單。
學習視頻鏈接:73-Python多線程-定時器_哔哩哔哩_bilibili
"""定時器"""
import threading
import time
def run():
print("定時器啟動了")
print(threading.current_thread()) # 查看當前正在執行的線程
timer = threading.Timer(1,run) #設置定時器 並實例化
timer.start() #啟動定時器
if __name__ =='__main__':
t1 = threading.Timer(1,function=run) #定時器定義 第一個參數是時間(每隔5秒干什麼) 第二個為執行函數 第三個為參數(如果存在參數的話)threading.Timer(5,function=run,args=5)
t1.start() #啟動定時器
while True:
time.sleep(2) #延時10秒
print("主線程運行中")
資料參考鏈接:Python的定時器_saltriver的專欄-CSDN博客_python 定時器
在使用Python定時器時需要注意如下4個方面:
(1)定時器構造函數主要有2個參數,第一個參數為時間,第二個參數為函數名,第一個參數表示多長 時間後調用後面第二個參數指明的函數。第二個參數注意是函數對象,進行參數傳遞,用函數名(如fun_timer)表示該對象,不能寫成函數 執行 語句fun_timer(),不然會報錯。用type查看下,可以看出兩者的區別。
print(type(fun_timer()))
print(type(fun_timer))
-------------------------------------------------------------------------------------------
輸出結果:
Hello Timer!
<class 'NoneType'>
<class 'function'>
(2)必須在定時器執行函數內部重復構造定時器,因為定時器構造後只執行1次,必須循環調用。
(3)定時器間隔單位是秒,可以是浮點數,如5.5,0.02等,在執 行函數fun_timer內部和外部中給的值可以不同。如上例中第一次執行fun_timer是1秒後,後面的都是5.5秒後執行。
(4)可以使用cancel停止定時器的工作,如下例:
# -*- coding: utf-8 -*-
import threading
import time
def fun_timer():
print('Hello Timer!')
global timer
timer = threading.Timer(5.5, fun_timer)
timer.start()
timer = threading.Timer(1, fun_timer)
timer.start()
time.sleep(15) # 15秒後停止定時器
timer.cancel()
-------------------------------------------------------------------------------------------
輸出結果:
Hello Timer!
Hello Timer!
Hello Timer!
視頻學習鏈接:74-Python多線程-隊列_哔哩哔哩_bilibili
"""隊列"""
import queue
import threading
import time
"""
import queue
queue.Queue() # 先入先出
queue.LifoQueue() # 後入先出
queue.PriorityQueue() # 可設置優先級
# 傳入參數maxsize設置可存儲數據的數量
Queue.put() # 往隊列放數據,block=False,timeout=15任一個都可以不等待,滿了就報錯
Queue.get() # 從隊列取數據,block=False,timeout=15任一個都可以不等待,空了就報錯
Queue.task_done() # 配合get使用,告訴隊列本次get完成
Queue.qsize() # 獲取數據的數量
Queue.full() # 判斷隊列是否滿
Queue.empty() # 判斷隊列是否空
Queue.join() # 等待線程完成
"""
q = queue.Queue(maxsize=3) # 實例化隊列 先入先出
q.put(1) # 往隊列放數據1
q.put(2) # 往隊列放數據2
print(q.full()) # 判斷隊列是否滿了
q.put(3) # 往隊列放數據3
print(q.full()) # 判斷隊列是否滿了
print(q.qsize()) # q.qsize()測量隊列現在的長度
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.empty()) # 判斷隊列是否為空
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.empty()) # 判斷隊列是否為空
print(q.qsize()) # q.qsize()測量隊列現在的長度
q = queue.PriorityQueue(maxsize=3) # 可設置優先級
q.put((1,"你好1")) # 往隊列放數據1
q.put((3,"你好3")) # 往隊列放數據2
print(q.full()) # 判斷隊列是否滿了
q.put((2,"你好2")) # 往隊列放數據3
print(q.full()) # 判斷隊列是否滿了
print(q.qsize()) # q.qsize()測量隊列現在的長度
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.empty()) # 判斷隊列是否為空
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.get()) # 取出隊列裡的數據 遵照先入先出的順序
print(q.empty()) # 判斷隊列是否為空
print(q.qsize()) # q.qsize()測量隊列現在的長度
q=queue.Queue(maxsize=10)
#生產者
def put_in():
count= 1
while True:
q.put(f'視頻{count}')
print(f'錄制的視頻{count}')
count+=1
time.sleep(1)
#消費者
def get_out(name):
while True:
print(f'{name}正在看視頻{q.get()}')
time.sleep(1)
if __name__=='__main__':
p = threading.Thread(target=put_in)
p.start()
g=threading.Thread(target=get_out,args=("小李", ))
g.start()
g1 = threading.Thread(target=get_out, args=("小雷",))
g1.start()
學習視頻鏈接:75-Python多線程-線程池_哔哩哔哩_bilibili
"""線程池"""
import time
from concurrent.futures import ThreadPoolExecutor
"""
線程池可以提高性能,防止啟動大量線程而導致系統變慢,可以更簡單的創建線程,適用於
突發的需要大量線程,而線程存在時間短的場景
"""
"""
線程池由concurrent.futures下的ThreadPoolExecutor提供
submit(fn, *args, **kwargs)將函數fn提交給線程池,後面是參數
map(fn, *iterables=None, chunksize=1)
shutdown(wait=True)關閉線程池
"""
"""
submit 函數提交後會返回一個Future對象
cancel()可以取消該線程,如果線程正在運行,不可取消,返回False,否則取消線程,並返回True
cancelled()返回線程是否被取消
running()返回線程是否正在運行
done()返回線程是否完成,包括取消和正常完成
result(timeout=None)獲取該線程的返回結果,會阻塞線程,timeout是阻塞時間
add_done_callback(fn)線程結束後執行fn函數
"""
def run(x):
print(f'線程{x}')
time.sleep(2)
return x * 10
#函數名可以隨便起
def callback(n):
print(n.result)
if __name__ == '__main__':
pool = ThreadPoolExecutor(max_workers=2)
future1 = pool.submit(run,1)
future2 = pool.submit(run, 2)
future3 = pool.submit(run, 3)
#查看線程1是否結束
print(future1.done())
time.sleep(3)
#查看線程2是否結束
print(future2.done())
#獲取線程1的返回值
print(future1.result())
#獲取線程3的返回值
#print(future3.result(timeout=1)) #等1秒之後沒有獲取到結果會報錯
# 獲取線程3的返回值 獲取不到就一直等待
print(future3.result())
print(future1.done())
time.sleep(3)
print(future2.done())
future1.add_done_callback(callback)#調用回調函數
pool.shutdown()#關閉線程池 關閉線程池後不能繼續添加線程
print("程序結束")