thread.local
执行多线程时,若使用普通全局变量,则多线程执行结果会相互影响,导致结果错误,见下方代码执行结果
import threading
import time
class A:
def __init__(self):
self.x = 0
count = A()
def add(n):
for i in range(int(n)):
count.x += i
print("count:",count.x)
t1 = threading.Thread(target=add,args='6')
t2 = threading.Thread(target=add, args='5')
t1.start()
t2.start()
执行结果:
为了解决多线程全局变量执行结果相互影响的问题,python提供 threading.local 类,将这个类实例化得到一个全局对象,不同的线程使用这个对象存储的数据其他线程看不见。
import threading
count = threading.local()
def add(n):
count.x = 0
for i in range(int(n)):
count.x += i
print("count:",count.x)
t1 = threading.Thread(target=add,args='6')
t2 = threading.Thread(target=add, args='5')
t1.start()
t2.start()
执行结果:
threading.local的实质
threading.local类构建了一个大字典,其元素是每一线程实例的地址为key和线程对象引用线程单独的字典的映射,如下:
{ id(Thread) -> (ref(Thread),thread-local dict) }
通过threading.local实例就可在不同的线程中,安全地使用线程独有的数据,做到了线程间数据隔离,如同本地变量一样安全。
定时器
threading.Timer继承自Thread,用来定义多久执行一个函数
class threading.Timer(interval, function, args=None, kwargs=None)
start方法执行之后,Timer对象会处于等待状态,等待了interval之后,开始执行function函数
如果在执行函数之前的等待阶段,使用了cancel方法,就会跳过执行函数结束。
等待interval后执行函数:
import threading
def add():
for i in range(10):
print("current thread_id:",threading.current_thread().ident)
time.sleep(1)
t1 = threading.Timer(3,add)
t1.start()
函数执行前加cancel方法:
import threading
def add():
for i in range(10):
print("current thread_id:",threading.current_thread().ident)
time.sleep(1)
t1 = threading.Timer(1,add)
t1.cancel()
t1.start()