写点什么

多线程 VS 多进程(一)

用户头像
若尘
关注
发布于: 2021 年 05 月 19 日
多线程 VS 多进程(一)

多线程 vs 多进程

  • 程序:一堆代码以文本形式存入一个文档

  • 进程:程序运行的一个状态

  • 包含地址空间、内容、数据栈等

  • 每个进程由自己完全独立的运行环境,多进程共享数据是一个问题

  • 线程

  • 一个进程的独立运行片段,一个进程可以有多个线程

  • 轻量化的进程

  • 一个进程的多个线程间共享数据和上下文运行环境

  • 共享互斥问题

  • 全局解释器锁(GTL)

  • python 代码的执行是由 python 虚拟机进行控制

  • 在主循环中只能有一个控制线程在执行

  • python 包

  • thread:有问题,不好用,python3 改成了_thread

  • threading:通行的包

  • 案例 01: 顺序执行,耗时比较长


        '''    利用time函数,生成两个函数    程序调试    计算总的运行时间    '''        import time    def loop1():        # ctime 得到当前时间        print("Start loop 1 at : ",time.ctime())        time.sleep(4)        print("End loop 1 at : ", time.ctime())        def loop2():        # ctime 得到当前时间        print("Start loop 2 at : ", time.ctime())        # 睡眠多长时间,单位是秒        time.sleep(2)        print("End loop 2 at : ", time.ctime())        def main():        print("Starting at : ", time.ctime())        loop1()        loop2()        print("All done at : ", time.ctime())        if __name__ == '__main__':        main()
复制代码


    Starting at :  Tue Aug 13 19:10:31 2019    Start loop 1 at :  Tue Aug 13 19:10:31 2019    End loop 1 at :  Tue Aug 13 19:10:35 2019    Start loop 2 at :  Tue Aug 13 19:10:35 2019    End loop 2 at :  Tue Aug 13 19:10:37 2019    All done at :  Tue Aug 13 19:10:37 2019
- 案例02:改用多线程,缩短总时间,使用_thread
复制代码


      '''    利用time函数,生成两个函数    程序调试    计算总的运行时间    '''        import time    import _thread as thread    def loop1():        # ctime 得到当前时间        print("Start loop 1 at : ",time.ctime())        time.sleep(4)        print("End loop 1 at : ", time.ctime())        def loop2():        # ctime 得到当前时间        print("Start loop 2 at : ", time.ctime())        # 睡眠多长时间,单位是秒        time.sleep(2)        print("End loop 2 at : ", time.ctime())        def main():        print("Starting at : ", time.ctime())        # 启动多线程的意思是用多线程去执行某个函数        # 启动多线程函数为start_new_thread        # 参数两个,一个是需要运行的函数名,第二个是函数的参数作为元组使用,为空则使用空元组        # 注意,如果函数只有一个参数,需要参数后有一个逗号        thread.start_new_thread(loop1, ())            thread.start_new_thread(loop2, ())            print("All done at : ", time.ctime())        if __name__ == '__main__':        main()        while True:            time.sleep(1)
复制代码


       Starting at :  Tue Aug 13 19:14:47 2019    All done at :  Tue Aug 13 19:14:47 2019    Start loop 1 at :  Tue Aug 13 19:14:47 2019    Start loop 2 at :  Tue Aug 13 19:14:47 2019    End loop 2 at :  Tue Aug 13 19:14:49 2019    End loop 1 at :  Tue Aug 13 19:14:51 2019- 案例03:多线程,传参数
复制代码


      # 利用time延时函数,生成两个函数    # 利用多线程调用    # 计算总运行时间    # 练习带参数的多线程启动方法    import time    # 导入多线程包并更名为thread    import _thread as thread        def loop1(in1):        # ctime 得到当前时间        print('Start loop 1 at: ', time.ctime())        # 把参数打印出来        print("我是参数", in1)        # 睡眠多长时间,单位是秒        time.sleep(4)        print('End loop 1 at: ', time.ctime())        def loop2(in1, in2):        # ctime 得到当前时间        print('Start loop 2 at: ', time.ctime())        # 把参数in1 和 in2 打印出来,代表使用        print("我是参数", in1, "和参数", in2)        # 睡眠多长时间,单位是秒        time.sleep(4)        print('End loop 2 at: ', time.ctime())        def main():        print("Starting at : ", time.ctime())        # 启动多线程的意思是用多线程去执行某个函数        # 启动多线程函数为start_new_thread        # 参数两个,一个是需要运行的函数名,第二个是函数的参数作为元组使用,为空则使用空元组        # 注意,如果函数只有一个参数,需要参数后有一个逗号        thread.start_new_thread(loop1, ("王老大", ))            thread.start_new_thread(loop2, ("王大鹏", "王晓鹏"))            print("All done at : ", time.ctime())        if __name__ == '__main__':        main()        # 一定要有while语句        # 因为启动多线程后本程序就作为主线程存在        # 如果主线程执行完毕,则子线程可能也需要终止        while True:           time.sleep(10)
复制代码


      Starting at :  Tue Aug 13 19:17:10 2019    All done at :  Tue Aug 13 19:17:10 2019    Start loop 1 at:  Tue Aug 13 19:17:10 2019    我是参数 王老大    Start loop 2 at:  Tue Aug 13 19:17:10 2019    我是参数 王大鹏 和参数 王晓鹏    End loop 1 at:  Tue Aug 13 19:17:14 2019    End loop 2 at:  Tue Aug 13 19:17:14 2019
复制代码


  • threading 的使用

  • 直接利用 threading.Thread 生成 Thread 实例

  • t = threading.Thread(target=xxx, args=(xxx, ))

  • t.start(): 启动多线程

  • t.join(): 等待多线程执行完成

  • 案例 04


          # 利用time延时函数,生成两个函数      # 利用多线程调用      # 计算总运行时间      # 练习带参数的多线程启动方法      import time      # 导入多线程包并更名为thread      import threading            def loop1(in1):          # ctime 得到当前时间          print('Start loop 1 at: ', time.ctime())          # 把参数打印出来          print("我是参数", in1)          # 睡眠多长时间,单位是秒          time.sleep(4)          print('End loop 1 at: ', time.ctime())            def loop2(in1, in2):          # ctime 得到当前时间          print('Start loop 2 at: ', time.ctime())          # 把参数in1 和 in2 打印出来,代表使用          print("我是参数", in1, "和参数 ", in2)          # 睡眠多长时间,单位是秒          time.sleep(2)          print('End loop 2 at: ', time.ctime())            def main():          print("Starting at: ", time.ctime())          # 生成threading.Thread实例          t1 = threading.Thread(target=loop1, args=("王老大",))          t1.start()                t2 = threading.Thread(target=loop2, args=("王大鹏", "王小鹏"))          t2.start()                print("All done at: ", time.ctime())            if __name__ == '__main__':          main()          # 一定要有while语句          # 因为启动多线程后本程序就作为主线程存在          # 如果主线程执行完毕,则子线程可能也需要终止          while True:              time.sleep(10)
复制代码


        Starting at:  Tue Aug 13 19:19:42 2019      Start loop 1 at:  Tue Aug 13 19:19:42 2019      我是参数 王老大      Start loop 2 at: All done at:  Tue Aug 13 19:19:42 2019      Tue Aug 13 19:19:42 2019      我是参数 王大鹏 和参数  王小鹏      End loop 2 at:  Tue Aug 13 19:19:44 2019      End loop 1 at:  Tue Aug 13 19:19:46 2019    5. 案例05:加入join后比较案例04的结果的异同
复制代码


          # 利用time延时函数,生成两个函数      # 利用多线程调用      # 计算总运行时间      # 练习带参数的多线程启动方法      import time      # 导入多线程包并更名为thread      import threading            def loop1(in1):          # ctime 得到当前时间          print('Start loop 1 at: ', time.ctime())          # 把参数打印出来          print("我是参数", in1)          # 睡眠多长时间,单位是秒          time.sleep(4)          print('End loop 1 at: ', time.ctime())            def loop2(in1, in2):          # ctime 得到当前时间          print('Start loop 2 at: ', time.ctime())          # 把参数in1 和 in2 打印出来,代表使用          print("我是参数", in1, "和参数 ", in2)          # 睡眠多长时间,单位是秒          time.sleep(2)          print('End loop 2 at: ', time.ctime())            def main():          print("Starting at: ", time.ctime())          # 生成threading.Thread实例          t1 = threading.Thread(target=loop1, args=("王老大",))          t1.start()                t2 = threading.Thread(target=loop2, args=("王大鹏", "王小鹏"))          t2.start()                t1.join()          t2.join()                print("All done at: ", time.ctime())            if __name__ == '__main__':          main()          # 一定要有while语句          # 因为启动多线程后本程序就作为主线程存在          # 如果主线程执行完毕,则子线程可能也需要终止          while True:              time.sleep(10)
复制代码


          Starting at:  Tue Aug 13 19:21:58 2019      Start loop 1 at:  Tue Aug 13 19:21:58 2019      我是参数 王老大      Start loop 2 at:  Tue Aug 13 19:21:58 2019      我是参数 王大鹏 和参数  王小鹏      End loop 2 at:  Tue Aug 13 19:22:00 2019      End loop 1 at:  Tue Aug 13 19:22:02 2019      All done at:  Tue Aug 13 19:22:02 2019    - 守护线程-daemon        - 如果在程序中将子线程设置成守护线程,则子线程会在主线程结束的时候自动退出        - 一般认为,守护线程不重要或者不允许离开主线程独立运行        - 守护线程案例能否有效果跟环境相关        - 案例06非守护线程
复制代码


              import time        import threading                def fun():            print("Start fun")            time.sleep(2)            print("end fun")                print("Main thread")                t1 = threading.Thread(target=fun, args=() )        t1.start()                time.sleep(1)        print("Main thread end")
复制代码


              Main thread        Start fun        Main thread end        end fun        - 案例07守护线程
复制代码


              import time        import threading                def fun():            print("Start fun")            time.sleep(2)            print("end fun")                print("Main thread")                t1 = threading.Thread(target=fun, args=() )        # 启动之前设置        t1.setDaemon(True)        # t1.daemon = True        t1.start()                time.sleep(1)        print("Main thread end")
复制代码


              Main thread        Start fun        Main thread end    - 线程常用属性        - threading.currentThread:返回当前线程变量        - threading.enumerate:返回一个包含正在运行的线程的list,正在运行的线程指的是线程启动后,结束前的状态        - threading.activeCount: 返回正在运行的线程数量,效果跟 len(threading.enumerate)相同        - thr.setName: 给线程设置名字        - thr.getName: 得到线程的名字        - 案例08
复制代码


              import time        import threading                def loop1():            # ctime 得到当前时间            print("Start loop 1 at : ",time.ctime())            time.sleep(6)            print("End loop 1 at : ", time.ctime())                def loop2():            # ctime 得到当前时间            print("Start loop 2 at : ",time.ctime())            time.sleep(1)            print("End loop 2 at : ", time.ctime())                def loop3():            # ctime 得到当前时间            print("Start loop 3 at : ",time.ctime())            time.sleep(5)            print("End loop 3 at : ", time.ctime())                def main():            print("Starting at: ", time.ctime())            # 生成threading.Thread实例            t1 = threading.Thread(target=loop1, args=( ))            # setName是给每一个子线程设置一个名字            t1.setName("THR_1")            t1.start()                    t2 = threading.Thread(target=loop2, args=( ))            t2.setName("THR_2")            t2.start()                    t3 = threading.Thread(target=loop3, args=( ))            t3.setName("THR_3")            t3.start()                    # 预期3秒后,thread2已经结束            time.sleep(3)            # enumerate 得到正在运行子线程,即子线程1和子线程3            for thr in threading.enumerate():                # getName能够得到线程的名字                print("正在运行的线程名字是:  {0}".format(thr.getName()))                    print("正在运行的子线程数量为:  {0}".format(threading.activeCount()))                    print("All done at: ", time.ctime())                        if __name__ == '__main__':            main()            # 一定要有while语句            # 因为启动多线程后本程序就作为主线程存在            # 如果主线程执行完毕,则子线程可能也需要终止            while True:                time.sleep(10)
复制代码


              Starting at:  Tue Aug 13 19:28:20 2019        Start loop 1 at :  Tue Aug 13 19:28:20 2019        Start loop 2 at :  Tue Aug 13 19:28:20 2019        Start loop 3 at :  Tue Aug 13 19:28:20 2019        End loop 2 at :  Tue Aug 13 19:28:21 2019        正在运行的线程名字是:  MainThread        正在运行的线程名字是:  THR_1        正在运行的线程名字是:  THR_3        正在运行的子线程数量为:  3        All done at:  Tue Aug 13 19:28:23 2019        End loop 3 at :  Tue Aug 13 19:28:25 2019        End loop 1 at :  Tue Aug 13 19:28:26 2019    - 直接继承自threading.Thread        - 直接继承Thread        - 重写run函数        - 类实例可以直接运行        - 案例09
复制代码


              import threading        import time                # 1. 类需要继承来自threading.Thread        class MyThread(threading.Thread):            def __init__(self, arg):                super().__init__()                self.arg = arg                    # 2. 必须重写run函数,run函数代表的是真正执行的功能            def run(self):                time.sleep(2)                print("The args for this class is {0}".format(self.arg))                for i in range(5):            t = MyThread(i)            t.start()            t.join()                print("Main thread is done!!!!!!!!")
复制代码


              The args for this class is 0        The args for this class is 1        The args for this class is 2        The args for this class is 3        The args for this class is 4        Main thread is done!!!!!!!!        - 案例10  工业风案例
复制代码


              import threading        from time import sleep, ctime                loop = [4, 2]                class ThreadFunc:            def __init__(self, name):                self.name = name                    def loop(self, nloop, nsec):                '''                :param nloop:loop函数的名称                :param nsec:系统休眠时间                :return:                '''                print('Start loop', nloop, 'at ', ctime())                sleep(nsec)                print('Done loop', nloop, 'at ', ctime())                def main():            print("Starting at: ", ctime())                    # ThreadFunc("loop").loop 跟以下两个式子相等            # t = ThreadFunc("loop")            # t.loop            # 以下t1 和 t2的定义方式相等            t = ThreadFunc("loop")            t1 = threading.Thread( target=t.loop, args=("LOOP1", 4))            # 下面这种写法更西方人,工业化一点            t2 = threading.Thread( target=ThreadFunc('loop').loop, args=('LOOP2', 2))                    # 常见错误写法            # t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4))            # t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2))                    t1.start()            t2.start()                    t1.join()            t2.join()                    print("All done at: ", ctime())                if __name__ == '__main__':            main()            # 一定要有while语句            # 因为启动多线程后本程序就作为主线程存在            # 如果主线程执行完毕,则子线程可能也需要终止            while True:                sleep(10)
复制代码


              Starting at:  Tue Aug 13 19:31:16 2019        Start loop LOOP1 at  Tue Aug 13 19:31:16 2019        Start loop LOOP2 at  Tue Aug 13 19:31:16 2019        Done loop LOOP2 at  Tue Aug 13 19:31:18 2019        Done loop LOOP1 at  Tue Aug 13 19:31:20 2019        All done at:  Tue Aug 13 19:31:20 2019
复制代码


发布于: 2021 年 05 月 19 日阅读数: 9
用户头像

若尘

关注

还未添加个人签名 2021.01.11 加入

还未添加个人简介

评论

发布
暂无评论
多线程 VS 多进程(一)