多线程的使用

作者: 布拉豆 | 来源:发表于2017-04-28 22:31 被阅读48次

    到目前为止,前面的章节文章都是单线程运行。就像一个人工作,必须一件事结束,再开始另一件事情,这就是所谓的单线程

    多线程就是雇佣多个人,一起做同一件事或者将不同的事分给不同的人去做,可以大幅度的提交效率

    先来看下多线程需要的库:Python内置的线程库threading

    线程的运行,通过threading,初始化得到一个实例,然后给他一个可以执行的函数,让他执行就不用管了,就像你在电脑上把音乐软件打开,然后隐藏到后台,它还是会继续工作,然后你继续做你的事情是一样的意思。

    能开一个线程,就能开多个线程.....

    在代码中初始化一个线程,并给他函数让他执行,他跑到后台去执行了,然后代码可以继续往下工作,先上一段代码理解下:

    import threading, time
    
    def loop():
        print("loop start run")
        time.sleep(5)
        print("loop exit")
    
    t = threading.Thread(target=loop, name="LoopThread")
    t.start()
    print("代码运行结束")
    

    解释一下代码:

    • 首先导入两个库,一个是线程threading,另一个是time库【主要是sleep函数】
    • 然后在代码中,定义了loop函数,执行操作有打印loop start run,接着睡眠5秒钟,接着打印loop exit
    • 再是初始化一个线程,目标函数是loop,给线程赋一个名字LoopThread
    • 启动线程,然后不管了,脚本代码打印代码运行结束之后退出

    先来看结果图:

    python多线程

    从结果图来看,整体运行了5秒,但是代码运行结束loop exit的前面,也就是说线程的运行情况和当前代码执行顺序无关,它只管运行它的。

    就像是我有个任务——执行loop函数,我嫌函数无聊不想执行,我就找一个人来把我这个任务拿去执行,然后我做我的事。

    理论上两个时间是重合的,时间会剪短,但是这里是看不出来的,因为代码执行的太快,时间和5秒相比毫无意义。

    接下来定义两个,来测试一下时间问题:

    import threading, time
    
    def loop():
        print("loop start run")
        time.sleep(5)
        print("loop exit")
    
    t1 = threading.Thread(target=loop, name="LoopThread-1")
    t2 = threading.Thread(target=loop, name="LoopThread-2")
    t1.start()
    t2.start()
    time.sleep(3)
    print("代码运行结束")
    

    这个示例是基于上一个示例的,现在创建两个线程,都在运行,理论上睡眠时间是5+5+3=13秒的,来看下具体执行情况:

    thread多线程加时

    还是短短的5.1秒,远小于13秒。

    简单说下为什么:t1睡眠5秒的时间和t2睡眠5秒是重合的,还有代码睡眠3秒是在5秒的时间范围内的,所以最后的运行时间也就是程序开始,到程序全部结束的时间。

    明白了线程的运行,然后继续了解下线程的其他知识点

    知识点一:父线程和子线程

    父线程和子线程是相对的。就拿刚才的示例来讲,代码执行是单线程,代码中创建了t1和t2,对于代码的单线程来讲,t1和t2是它的子线程,因为他们是被代码的单线程创建出来的。

    知识点二:守护线程

    守护线程和普通线程基本没什么区别,但是有一点特殊,即守护线程还没执行完,主线程退出,守护线程会强制退出;但是主线程执行结束,普通线程没结束,主线程会等待普通线程结束再退出

    上一个示例代码和运行结果图:

    import threading, time
    
    def loop():
        print("loop start run")
        time.sleep(5)
        print("loop exit")
    t = threading.Thread(target=loop, name="LoopThread")
    t.setDaemon(True)
    t.start()
    print("代码运行结束")
    
    Python守护线程

    子线程还没结束,主线程已经结束了,强制退出,运行时间仅0.2秒。

    对比本文第一个示例【非守护线程】,总执行时间有5.1秒呢

    知识点三:线程和进程

    线程:线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。一个线程是一个execution context(执行上下文),即一个cpu执行时所需要的一串指令。

    进程:一个程序的执行实例就是一个进程。每一个进程提供执行程序所需的所有资源。(进程本质上是资源的集合)

    一个进程有一个虚拟的地址空间、可执行的代码、操作系统的接口、安全的上下文(记录启动该进程的用户和权限等等)、唯一的进程ID、环境变量、优先级类、最小和最大的工作空间(内存空间),还要有至少一个线程。

    知识点四:Python的线程是鸡肋?

    用C、C++来写死循环,直接可以把全部核心跑满,4核就跑到400%,8核就跑到800%,但是Python是不行的。

    因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

    Python3更多教程——传送门

    相关文章

      网友评论

        本文标题:多线程的使用

        本文链接:https://www.haomeiwen.com/subject/mxmazttx.html