多线程 VS 多进程(一)

举报
ruochen 发表于 2021/03/26 22:46:30 2021/03/26
【摘要】 多线程 vs 多进程 程序:一堆代码以文本形式存入一个文档 进程:程序运行的一个状态 包含地址空间、内容、数据栈等每个进程由自己完全独立的运行环境,多进程共享数据是一个问题 线程 一个进程的独立运行片段,一个进程可以有多个线程轻量化的进程一个进程的多个线程间共享数据和上下文运行环境共享互斥问题 全局解释器锁(GTL) python 代码的执行是由python ...

多线程 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()
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
        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
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 案例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)
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
        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
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 案例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)
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
        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
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
  • threading的使用

    • 直接利用threading.Thread生成Thread实例
      1. t = threading.Thread(target=xxx, args=(xxx, ))
      2. t.start(): 启动多线程
      3. t.join(): 等待多线程执行完成
      4. 案例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)
        
                
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
         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
        
                
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      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)
        
                
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
         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
        
                
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 守护线程-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")
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
            Main thread
            Start fun
            Main thread end
            end fun
          
                    
                   
          • 1
          • 2
          • 3
          • 4
        • 案例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")
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
            Main thread
            Start fun
            Main thread end
          
                    
                   
          • 1
          • 2
          • 3
      • 线程常用属性
        • 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)
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
            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
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
      • 直接继承自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!!!!!!!!")
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
            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!!!!!!!!
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
        • 案例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)
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
            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
          
                    
                   
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6

文章来源: ruochen.blog.csdn.net,作者:若尘,版权归原作者所有,如需转载,请联系作者。

原文链接:ruochen.blog.csdn.net/article/details/99461907

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。