定时器:
在实际应用中,我们经常需要使用定时器去触发一些事件。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("程序结束")