当前位置:首页 > Python教程 > python技巧

Python之并发编程(五)多线程

  1. 多线程的概念介绍

    threading模块介绍:threading模块和multiprocessing模式在使用层面,有甚大的相似性

  2. 开启多线程的两种方式

    1. 开启进程的第一种方式:

      #1.创建线程的开销比创建进程的开销小,因而创建线程的速度快 from multiprocessing import Processfrom threading import Threadimport osimport timedef work():
          print('<%s> is running'%os.getpid())
          time.sleep(2)
          print('<%s> is done'%os.getpid())if __name__ == '__main__':
          t=Thread(target=work,)
          # t= Process(target=work,)     t.start()
          print('主',os.getpid())#开启进程的第一种方式 
    2. 开启进程的第二种方式(用类):

      from threading import Threadimport timeclass Work(Thread):
          def __init__(self,name):
              super().__init__()
              self.name = name
          def run(self):
              # time.sleep(2)         print('%s say hell'%self.name)if __name__ == '__main__':
          t = Work('egon')
          t.start()
          print('主')#开启线程的第二种方式(用类) 
  3. 在一个进程开启多个线程与在一个进程下开始多个子进程的区别:

    1. 线程的开启速度大于进程的开启速度

      from  multiprocessing import Processfrom threading import Threadimport timedef work():
          time.sleep(2)
          print('hello')if __name__ == '__main__':
          t = Thread(target=work)#如果等上几秒,他会在开启的过程中先打印主,如果不等会先打印hello     # t = Process(target=work) #子进程会先打印主,     t.start()
          print('主')
          #线程的开启速度大于进程的开启速度 
    2. 在同一个进程下开多个进程和开多个线程的pid不同

      # 2.---------- from  multiprocessing import Processfrom threading import Threadimport osdef work():
          print('hello',os.getpid())if __name__ == '__main__':
          #在主进程下开启多个线程,每个线程都跟主进程的pid一样     t1= Thread(target=work)
          t2 = Thread(target=work)
          t1.start()
          t2.start()
          print('主线程pid',os.getpid())
      
          #来多个进程,每个进程都有不同的pid     p1 = Process(target=work)
          p2 = Process(target=work)
          p1.start()
          p2.start()
          print('主进程pid', os.getpid())#在同一个进程下开多个进程和开多个线程的pid的不同 
    3. 同一进程内的线程共享该进程的数据

      from  threading import Threadfrom multiprocessing import  Processimport osdef work():
          global n
          n-=1     print(n)  #所以被改成99了 n = 100 if __name__ == '__main__':
          # p = Process(target=work)     p = Thread(target=work)  #当开启的是线程的时候,因为同一进程内的线程之间共享进程内的数据                             #所以打印的n为99     p.start()
          p.join()
          print('主',n) #毫无疑问子进程p已经将自己的全局的n改成了0,     # 但改的仅仅是它自己的,查看父进程的n仍然为100 #同一进程内的线程共享该进程的数据 

      线程和进程的区别:

      1. 开启进程的开销非常大,比开启线程的开销大很多.
      2. 开启线程的速度非常快.要快几十倍到上百倍.
      3. 线程线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信.
  4. 线程的一些方法

    from threading import Threadfrom threading import currentThreadfrom threading import  enumerate from threading import activeCountimport timeimport osdef task():
        time.sleep(2)
        print('666')if __name__ == '__main__':
        t1 = Thread(target=task,name='线程1')
        t2 = Thread(target=task,name='线程2')
        t1.start()
        t2.start()
    
        print(t1.isAlive())   # 判断线程是否还在活动 返回布尔值     print(t1.getName())   # 获取线程名称     t1.setName('gou')     # 设置线程名称     print(t1.name)      
        print(currentThread())   # 获取当前线程     print(enumerate())   # 获取当前进程下所有线程,并以列表形式返回     print(activeCount())   # 获取还在活动的线程数     print(f"==主线程{os.getpid()}")# 结果: True 线程1 gou
    <_MainThread(MainThread, started 11472)>
    [<_MainThread(MainThread, started 11472)>, <Thread(gou, started 1876)>, <Thread(线程2, started 8760)>]3 ==主线程12980 666 666 
  5. join和守护进程

    • join: 阻塞 告知主线程要等待我子线程执行完毕之后再执行主线程

      from threading import Threadimport timedef task(name):
          print(f'{name} is running')
          time.sleep(1)
          print(f'{name} is gone')if __name__ == '__main__':
          start_time = time.time()
          t1 = Thread(target=task,args=('海狗',))
          t2 = Thread(target=task,args=('海狗1',))
          t3 = Thread(target=task,args=('海狗2',))
      
          t1.start()
          t1.join()   
          t2.start()
          t2.join()
          t3.start()
          t3.join()
      
          print(f'===主线程{time.time() - start_time}')  # 线程是没有主次之分的. # 结果: 海狗 is running
      海狗 is gone
      海狗1 is running
      海狗1 is gone
      海狗2 is running
      海狗2 is gone
      ===主线程3.0049641132354736 
    • 守护线程:守护线程 等待非守护子线程以及主线程结束之后,结束.

      from threading import Threadimport timedef sayhi(name):
          print('你滚!')
          time.sleep(2)
          print('%s say hello' %name)if __name__ == '__main__':
          t = Thread(target=sayhi,args=('egon',))
          # t.setDaemon(True) #必须在t.start()之前设置     t.daemon = True    # 设置线程的两种方式     t.start()  # 线程的开启速度要跟进程开很多     print('主线程')# 结果: '你滚!' '主线程' 
      from threading import Threadimport timedef foo():
          print(123)  # 1     time.sleep(1)
          print("end123")  # 4 def bar():
          print(456)  # 2     time.sleep(3)
          print("end456")  # 5 t1=Thread(target=foo)
      t2=Thread(target=bar)
      
      t1.daemon=True t1.start()
      t2.start()print("main-------")  # 3 
    • 面试题

      from threading import Threadimport timedef foo():
          print(123)  # 1     time.sleep(1)
          print("end123")  # 4 def bar():
          print(456)  # 2     time.sleep(3)
          print("end456")  # 5 t1=Thread(target=foo)
      t2=Thread(target=bar)
      
      t1.daemon=True t1.start()
      t2.start()print("main-------")  # 3 # 结果: 123 456 main-------
      end123
      end456
  6. 互斥锁

    • 多个任务共抢一个数据,保证数据的安全的目的,要让其串行

      from threading import Threadimport timeimport random
      x = 100 def task():
          global x
          temp = x
          time.sleep(random.randint(1, 3))
          temp = temp - 1     x = tempif __name__ == '__main__':
          l1 = []
          for i in range(100):
              t = Thread(target=task)
              l1.append(t)
              t.start()
      
          for i in l1:
              i.join()
          print(f'主线程{x}')# 结果:  # 相当于对全局变量赋值100次99 主线程99 
      from threading import Threadfrom threading import Lockimport timeimport random
      x = 100 def task(lock):
      
          lock.acquire()
          # time.sleep(random.randint(1,2))     global x
          temp = x
          time.sleep(0.01)
          temp = temp - 1     x = temp
          lock.release()if __name__ == '__main__':
          mutex = Lock()
          l1 = []
          for i in range(100):
              t = Thread(target=task,args=(mutex,))
              l1.append(t)
              t.start()
      
          time.sleep(3)
          print(f'主线程{x}')# 结果: 主线程0

【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐