一.线程的调用
1.无参
def run_01(): for i in range(6, 10): print("test01", i) time.sleep(1) th_01 = threading.Thread(target=run_01) # 创建线程 th_01.start() # 启动线程 for i in range(0, 5): print("main", i) time.sleep(1)
threading中最主要的类就是Thread,我们可通过实例化Thread类来创建一个子线程,target参数为运行的事件。
start()方法为启动线程,线程运行结束或报异常时自动会结束线程。
程序默认在主线程上运行,不做任何操作的话,子线程和主线程是同步进行的。
2.有参
def run_01(a): for i in range(6, 10): print("test01", i) time.sleep(1) th_01 = threading.Thread(target=run_01, args=("test",)) # 创建线程 th_01.start() # 启动线程
若运行的事件有参数时,我们可通过args传入一个元组入参,也可通过kwargs传入字典类型。
def run_01(a): for i in range(6, 10): print("test01", i) time.sleep(1) th_01 = threading.Thread(target=run_01, kwargs={"a": "test"}) # 创建线程 th_01.start() # 启动线程
key值要与参数值保持一致。
3.多参
def run_01(a, b): for i in range(6, 10): print("test01", i) time.sleep(1) th_01 = threading.Thread(target=run_01, args=(1, 2)) # 创建线程 # or # th_01 = threading.Thread(target=run_01, kwargs={"a": "test", "b": 1}) # 创建线程 th_01.start() # 启动线程
和单个入参差不多,多传入一个参数即可。
二.设置线程名称,获取线程状态
1.子线程名称默认是Thread-1,Thread-2.....,我们可通过Thread类中name属性设置线程名,
def run(): for i in range(0, 5): print(i) thread = threading.Thread(target=run, name='test') # name设置线程名 print(thread.name, thread.getName()) # name,getname()方法获取线程名
通过name属性和getName()方法获取线程名。修改/设备线程名也可通过setName()方法设置。
thread = threading.Thread(target=run, name='test') # name设置线程名 thread.setName("updateThreadName") print(thread.name, thread.getName()) # name,getName()方法获取线程名
2.is_alive()为获取线程当前的运行状态
def run(): for i in range(0, 5): print(i) thread = threading.Thread(target=run, name='test') # name设置线程名 thread.start() bol = thread.is_alive() # 为true时表示正在运行,为false时停止运行 print(bol)
三.主/子线程执行顺序
1.默认情况下主/子线程会同时执行,主线程会等待子线程结束后再结束。
def run(): for i in range(0, 5): print("thread", i) time.sleep(2) if __name__ == '__main__': thread = threading.Thread(target=run) thread.start() for i in range(5, 10): print("main", i) time.sleep(1)
2.Thread类中有个daemon属性可控制执行结果
if __name__ == '__main__': thread = threading.Thread(target=run,daemon=True) thread.start() for i in range(5, 10): print("main", i) time.sleep(1)
创建子线程时我们将daemon设置为True,可以看出主线程结束后子线程也会结束运行,
不会等待子线程结束后再结束。也可通过setDaemon()方法设置。
if __name__ == '__main__': thread = threading.Thread(target=run) thread.setDaemon(True) thread.start() for i in range(5, 10): print("main", i) time.sleep(1)
四.join()用法
1.join()为堵塞主线程执行,优先执行子线程,等子线程执行完后再去执行主线程。
def run(): for i in range(0, 5): print("thread1", i) time.sleep(1) def run2(): for i in range(0, 5): print("thread2", i) time.sleep(1) if __name__ == '__main__': thread = threading.Thread(target=run) thread2 = threading.Thread(target=run2) thread.start() thread.join() # 开始堵塞主线程,只执行thread线程 thread2.start() for i in range(5, 10): print("main", i) time.sleep(1)
2.join(timeout=None)中timeout参数
timeout默认为None,可传递秒数,设置堵塞主线程的时间,timeout秒后不管子线程有没有运行完都会执行主线程。
thread.join(timeout=2.0)
五.Event()方法的使用
我们都知道一个进程有多个线程,多个线程之间的资源是共享的,那么如果多个线程去修改同
一个资源数据,就会出现数据错乱的情况。Event类可以去堵塞线程的运行,我们先来看下Event()的几个方法。
1.实例化Event()类
event = threading.Event()
Event()中有个_flag的私有属性,默认为false,表示堵塞
2.wait()调用后表示开始堵塞
event.wait(timeout=2.0) # 调用该方法后,该线程会被堵塞,timeout为堵塞时间
3.set()方法设置flag为true,表示结束堵塞
event.set() # 设置self._flag = True
4.清除设置,flag值恢复false,继续堵塞
event.clear() # self._flag = False
5.is_set()查看flag的值
print(event.is_set()) # 查看当前_flag的值
6.实例
import threading import time def run(event): print("当前flag的值", event.is_set()) event.wait() # 开始堵塞 for i in range(1, 6): print(i) time.sleep(1) if event.is_set() == False: break event = threading.Event() # self._flag = False thread = threading.Thread(target=run, args=(event,)) thread.start() print("\n开始堵塞2s") time.sleep(2) event.set() # 设置self._flag = True print("结束堵塞,运行2s") time.sleep(2) print("结束运行,跳出for循环") event.clear() # self._flag = False
解析:
上述中,子线程执行到event.wait()时就开始进行堵塞,主线程等待2s后调用set()方法使子线程继续运行,
子线程循环两次后主线程调用clear()设置flag值为false,子线程if判断跳出循环,运行结束。
文章来源:https://www.cnblogs.com/lihongtaoya/ ,请勿转载