zoukankan      html  css  js  c++  java
  • 多线程编程threading

    操作系统能够调度和切换的最小单元实际上是线程。
    对于IO操作来说,多线程和多进程性能差别不大。
    有两种方法可以进行多线程编程。

    1.使用多线程编程的两种方法

    (1)直接实例化一个Thread对象

    from threading import Thread
    import time
    
    def task1():
        print("task1开始执行")
        time.sleep(5)
        print("task1执行结束")
    
    def task2():
        print("task2开始执行")
        time.sleep(3)
        print("task2结束执行")
    
    if __name__ == "__main__":
        t1 = Thread(target=task1)
        t2 = Thread(target=task2)
        start_time = time.time()
        t1.start()
        t2.start()
        run_time = time.time() - start_time
        print("执行时间:%s"%run_time)

    执行结果:
      task1开始执行
      task2开始执行
      执行时间:0.0009980201721191406
      task2结束执行
      task1执行结束

    t1和t2属于并发执行,t1和t2开始之后,并不会等到执行完毕之后再执行下面的代码。
    因为在t1和t2之外还有一个主线程,我们通过debug可以看的一清二楚。

    在主线程结束之后,会等待其中的子线程全部执行完毕之后才会退出,不然就不会打印子线程的结果信息。
    我们可以做一些设置:
      t1.setDaemon(True)

    执行结果:
      task1开始执行
      task2开始执行
      执行时间:0.0009980201721191406
      task2开始执行
    setDaemon的意思是,将t1设置为守护线程,当主线程结束之后,守护线程也会随之结束。

    如果你希望一定要等待线程执行完成,可以适用join。

    from threading import Thread
    import time
    
    def task1():
        print("task1开始执行")
        time.sleep(5)
        print("task1执行结束")
    
    def task2():
        print("task2开始执行")
        time.sleep(3)
        print("task2结束执行")
    
    if __name__ == "__main__":
        t1 = Thread(target=task1)
        t1.setDaemon(True)  #主线程不用等待t1执行完毕之后才退出,但是依然要等待t2执行完毕。
        t2 = Thread(target=task2)
        start_time = time.time()
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        run_time = time.time() - start_time
        print("执行时间:%s"%run_time)
        
    执行结果:
        task1开始执行
        task2开始执行
        task2结束执行
        task1执行结束
        执行时间:5.0016233921051025

    加入join之后,不管你是否设置了守护线程,都会等到线程执行结束,才会接着往下执行。

    (2)直接继承Thread类,重写run方法

    from threading import Thread
    import time
    
    class T1(Thread):
        def run(self):
            print("task1开始执行")
            time.sleep(5)
            print("task1执行结束")
    
    class T2(Thread):
        def run(self):
            print("task2开始执行")
            time.sleep(3)
            print("task2结束执行")
    
    
    
    if __name__ == "__main__":
        t1 = T1()
        t2 = T2()
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print("主线程结束")

    两种方式其实是一样的,一个是作为子类一个是作为对象,方法和属性基本相同。
    同时我们也可以通过super调用父类的__init__方法。

    在代码逻辑比较简单的时候,适用第一种方法没有什么毛病,如果逻辑比较复杂使用第二种方法当然更合适。
    不管你要适用那种方法,你都是操作的一个对象,如果你想获取结果,当然应该把结果绑定到对象上去。

    2.Thread中的方法一览

    daemon:等于isDaemon
    getName:获取线程名
    ident:线程标识符
    isAlive:查看线程的运行状态
    isDaemon:是否是守护线程
    is_alive
    join:等待线程执行完毕
    name:property属性,可以给线程设置name
    run:线程的逻辑部分,一般会重写这个方法
    setDaemon:设置守护线程
    setName:设置线程名
    start:开始执行线程

  • 相关阅读:
    oracle之 关闭透明大页
    Mac下使用sublime Text打开隐藏目录
    win下gosublime配置ctag
    Qless 相关知识
    Redis 的 Lua 脚本支持
    HTTP TCP UDP Socket 关系的几个经典图
    golang rpc 简单范例
    golang fatal error: all goroutines are asleep
    JSON 解析的可抛弃
    golang label breaks
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/11289763.html
Copyright © 2011-2022 走看看