链接1:【python】多线程(笔记)(1)
链接2:【python】多线程(笔记)(2)Queue队列
0.问题描述
两个线程,但是不同延时时长,导致数据输出频率不同,但是又想基于其中的最大频率实时输出数据(比如线程一与线程二均用来描述某个物体的运动,但是线程一每2秒输出数据,线程二每1秒输出数据,输出数据方式为[线程一数据,线程二数据],希望屏幕每1秒打印出该数据),但是队列中,以后进先出队列为例,数据每取出之后队列就少一个数据,这就需要用global全局变量作为中间值。
1.示例代码
两个线程,func1与func2,
func1的参数从0开始每2秒自增一次并输入到中间队列中,
func2每1秒从中间队列取出最新的参数并打印到屏幕上:如果队列不为空,则打印最新参数;如果为空,则打印历史参数
中间队列设为q
则逻辑如下:
示例代码如下所示:
注意代码逻辑顺序,非常重要!!!
import threading
import time
import queue
q=queue.LifoQueue()#后进先出队列,队列长度无限制
global qqq
global ppp
ppp=-1#线程二的初始值,为了区别这里给ppp赋值-1
qqq=-2#线程一的初始值
#这两个参数赋值为负仅为了鉴别线程是否会被执行
#由于线程一在下面的threads中优先于线程二执行,屏幕上不会打印出-1与-2
#线程一
def func1():#func1每2秒自增一次
global qqq
q1=0
for i in range(5):
q1=q1+1
qqq=q1
q.put(qqq)#最新的qqq值写入q队列中
print ("线程一q1: %s, %s" %(qqq,time.ctime()))
time.sleep(2)#每2秒向q线程中填入新值
#线程二
def func2():#func2每1秒向线程中取值
#global qqq
global ppp
for i in range(10):
if q.qsize()==0:#如果q线程为空,赋历史值
qqqqq=ppp
print ("线程二q2: %s, %s" %(qqqqq,time.ctime()))
else:#如果q线程不为空,赋新值
q2=q.get([i])#func2获取q队列数据,因为后进先出,因此获取的都是最新数据
ppp=q2
print ("线程二q2: %s, %s" %(q2,time.ctime()))
time.sleep(1)#每1秒向q线程中取值
#定义线程
threads = []
t1 = threading.Thread(target=func1)#这里谁是t1谁先执行
threads.append(t1)
t2 = threading.Thread(target=func2)#这里谁是t2谁后执行
threads.append(t2)
#主程序/主线程
if __name__ == '__main__':
for t in threads:#按照顺序执行threads的内容
t.setDaemon(True)
t.start()
t.join()#子线程优先
print ("qqq %s" %qqq)#查看qqq的最新值
print ("all over %s" %time.ctime())#查看结束时刻
print("queue size= %s" %queue.Queue.qsize(q))#查看队列大小
输出结果:
只看q1,每两秒自增并输出一次,正确
只看q2,每一秒输出一次,输出的都是q1的最新值,正确
错误情况一:给队列提前赋值
导致队列不为空,影响后续输出
错误代码:(第11行提前给队列赋值)
import threading
import time
import queue
q=queue.LifoQueue()#后进先出队列,队列长度无限制
global qqq
global ppp
ppp=-1#线程二的初始值为了区别这里给ppp赋值-1
qqq=-2#先给qqq赋值,然后写入队列中否则func2一开始无法获取数据
q.put(qqq)#提前给队列赋值
#线程一
def func1():#func1每2秒自增一次
global qqq
q1=0
for i in range(5):
q1=q1+1
qqq=q1
q.put(qqq)#最新的qqq值写入q队列中
print ("线程一q1: %s, %s" %(qqq,time.ctime()))
time.sleep(2)#每2秒向q线程中填入新值
#线程二
def func2():#func2每1秒向线程中取值
#global qqq
global ppp
for i in range(10):
if q.qsize()==0:#如果q线程为空,赋历史值
qqqqq=ppp
print ("线程二q2: %s, %s" %(qqqqq,time.ctime()))
else:#如果q线程不为空,赋新值
q2=q.get([i])#func2获取q队列数据,因为后进先出,因此获取的都是最新数据
ppp=q2
print ("线程二q2: %s, %s" %(q2,time.ctime()))
time.sleep(1)#每1秒向q线程中取值
#定义线程
threads = []
t1 = threading.Thread(target=func1)#, args=[qqq])
threads.append(t1)
t2 = threading.Thread(target=func2)#, args=[qqq])
threads.append(t2)
#主程序/主线程
if __name__ == '__main__':
for t in threads:#按照顺序执行threads的内容
t.setDaemon(True)
t.start()
t.join()#子线程优先
print ("qqq %s" %qqq)#查看qqq的最新值
print ("all over %s" %time.ctime())#查看结束时刻
print("queue size= %s" %queue.Queue.qsize(q))#查看队列大小
错误结果:
由于队列被提前赋值,导致17:43:16秒时队列不为空,队列中最开始被赋值的-2被取出
错误情况二:线程逻辑顺序反了
正确的情况是func1先自增、将参数写入队列,func2再取数
反过来的话,func2先取数,此时若未提前定义队列,可能会引起错误
错误代码:
import threading
import time
import queue
q=queue.LifoQueue()#后进先出队列,队列长度无限制
global qqq
global ppp
ppp=-1#线程二的初始值为了区别这里给ppp赋值-1
qqq=-2#先给qqq赋值,然后写入队列中否则func2一开始无法获取数据
#q.put(qqq)#先给qqq赋值,然后写入队列中否则func2一开始无法获取数据
#线程一
def func1():#func1每2秒自增一次
global qqq
q1=0
for i in range(5):
q1=q1+1
qqq=q1
q.put(qqq)#最新的qqq值写入q队列中
print ("线程一q1: %s, %s" %(qqq,time.ctime()))
time.sleep(2)#每2秒向q线程中填入新值
#线程二
def func2():#func2每1秒向线程中取值
#global qqq
global ppp
for i in range(10):
if q.qsize()==0:#如果q线程为空,赋历史值
qqqqq=ppp
print ("线程二q2: %s, %s" %(qqqqq,time.ctime()))
else:#如果q线程不为空,赋新值
q2=q.get([i])#func2获取q队列数据,因为后进先出,因此获取的都是最新数据
ppp=q2
print ("线程二q2: %s, %s" %(q2,time.ctime()))
time.sleep(1)#每1秒向q线程中取值
#定义线程
threads = []
t1 = threading.Thread(target=func2)#, args=[qqq])
threads.append(t1)
t2 = threading.Thread(target=func1)#, args=[qqq])
threads.append(t2)
#主程序/主线程
if __name__ == '__main__':
for t in threads:#按照顺序执行threads的内容
t.setDaemon(True)
t.start()
t.join()#子线程优先
print ("qqq %s" %qqq)#查看qqq的最新值
print ("all over %s" %time.ctime())#查看结束时刻
print("queue size= %s" %queue.Queue.qsize(q))#查看队列大小
错误结果:线程二先被启动而且输出错误数据
这里
#定义线程
threads = []
t1 = threading.Thread(target=func2)#, args=[qqq])
threads.append(t1)
t2 = threading.Thread(target=func1)#, args=[qqq])
threads.append(t2)
导致func2先被执行,正确的应该是
#定义线程
threads = []
t1 = threading.Thread(target=func1)#, args=[qqq])
threads.append(t1)
t2 = threading.Thread(target=func2)#, args=[qqq])
threads.append(t2)