• 线程(Thread)基本用法


    一.线程的调用

    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/ ,请勿转载
  • 相关阅读:
    WebSocket
    华为云云耀云服务器L实例评测|在 Centos & Docker 中使用Nginx部署Vue项目
    【JavaWeb】FilterConfig应用示例
    二叉树的三种遍历方式
    【C++】set & map的使用
    Kotlin MutableStateFlow
    Java方法
    【Redis】高可用:主从复制详解
    Bean的作用域和生命周期
    C++类的自动类型转换和强制类型转换
  • 原文地址:https://www.cnblogs.com/lihongtaoya/p/16862244.html