美文网首页python线程相关
多线程 -- threading

多线程 -- threading

作者: 钱塘 | 来源:发表于2017-08-18 15:02 被阅读53次

    多线程模块 threading

    • 创建多线程的两种方式:

      
      import threading
      import time
      
      
      
    • 创建线程的第一种方式

      def foo(n):
          pass
      print('hello world')
          
      t1 = threading.Thread(target=foo, args=(1,))
      t1.start()
      
    • 创建线程的第二种方式

    ``` 
    class MyThread(threading.Thread):
    
        def __init__(self, num):
            threading.Thread.__init__(self)
            self.num = num   # 对象里的字段  # self 是 t1或t2
    
        def run(self):
    
            print("running on number: %s" % self.num)
    
            time.sleep(3)
    
    if __name__ == '__main__':
        t1 = MyThread(1)  # 实例化一个类的对象,执行构造方法
        t2 = MyThread(2)
    
        t1.start()
        t2.start()
    ``` 
    
    • 创建线程:
        import threading
        t1 = threading.Thread(target=music, args=('七里香',))
        
        target指向函数,args指向函数的参数
    
    • 启动线程:

        t.start()
      
    • 阻塞线程:

        t.join()    阻塞直到线程t结束   
      
    • 多线程实例1

        import threading
        from time import ctime, sleep
        import time
            
        # 预计耗时4秒
        def music(func):
            for i in range(2):
                print("I was listening to %s. %s" % (func, ctime()))
                sleep(2)
                print("end listening %s" %ctime())
        
        # 预计耗时6秒
        def movie(func):
            for i in range(2):
                print("Begin watching at the %s! %s" % (func,ctime()))
                sleep(3)
                print("end watching %s" % ctime())
        
        
        # 创建线程1,2
        
        threads = []
        t1 = threading.Thread(target=music, args=('七里香',))
        threads.append(t1)
        t2 = threading.Thread(target=movie, args=('十三区',))
        threads.append(t2)
        
        
        if __name__ == '__main__':
            for t in threads:
                t.start()
            start = time.time()
            t2.join()
            end = time.time()
        
        
            # t2.join()    # join阻塞
            print("总共耗时 %s" % (end-start))
            
            
        # 结果:总共耗时 6.004828929901123
      
    • 多线程 -- 计算密集型

      import threading
      import time
      
      begin = time.time()
      
      def add(n):
          sum = 0
          for i in range(n):
              sum += i
          print(sum)
      
      
      # 单线程串行计算
      # add(10000000)
      # add(10000000)
      
      
      # 多线程并行计算
      t1 = threading.Thread(target=add, args=(10000000,))
      t1.start()
      # print('1开始了')
      
      t2 = threading.Thread(target=add, args=(10000000,))
      t2.start()
      # print('2也开始了')
      
      t1.join()
      t2.join()
      #
      end = time.time()
      
      print(end-begin)
      
      
      # 串行花费 14.73 秒  两者都是计算密集型,都在抢CPU
      # 并行花费 15.71 秒  并行反而更多,因为切换还需要时间
      
      # IO密集型任务或函数
      # 计算密集型任务
      
      # GIL全局解释锁  如果只有一颗CPU,无法解决计算密集型的任务 只有Cpython有这个bug
      
    • 多线程 -- IO密集型

      import time
      import threading
      
      
      def foo(n):                         # 设定3秒
          print('线程1开始')
          print('foo %s' % n)
          # print('foo')
          time.sleep(3)
          print('线程1结束\n')
      
      
      def bar(n):                         # 设定1秒
          print('线程2开始')
          print('bar %s' % n)
          time.sleep(1)
          # print('ok')
          print('线程2结束')
      
      
      # t1 t2 即为线程
      # target = 要执行的函数 args = 参数
      t1 = threading.Thread(target=foo, args=(1,))
      t2 = threading.Thread(target=bar, args=(2,))
      
      print('...... in the main  ........')
      
      # 线程执行 start()
      
      begin = time.time()
      
      t1.start()  # 线程开始
      t2.start()  # 线程开始
      
      t1.join()  # 子线程不结束不往下走
      t2.join()  # 子线程不结束不往下走
      
      end = time.time()
      print('整个程序一共花了', end - begin, '秒,asshole')  #
      
      
      # 运行结果: 整个程序一共花了 3.003476858139038 秒,asshole
          
      
    • 死锁

      # 死锁怎么办?
      # 用递归锁解决死锁问题,递归锁可重用
      
      import threading, time
      
      class myThread(threading.Thread):
      
      def doA(self):
          # lockA.acquire()
          lock.acquire()                  # 加锁        # 为什么在外面加了一把锁后还要在里面再加一把锁
          print(self.name, "gotlockA", time.ctime())
          time.sleep(1)
          # lockB.acquire()
          lock.acquire()                  # 加第二把锁
          print(self.name, "gotlockB", time.ctime())
          # lockB.release()
          lock.release()                  # 释放第一把锁
          # lockA.release()
          lock.release()                  # 释放第二把锁
      
      def doB(self):
          lock.acquire()
          print(self.name, "gotlockB", time.ctime())
          time.sleep(1)
          lock.acquire()
          print(self.name, "gotlockA", time.ctime())
          lock.release()
          lock.release()
      
      def run(self):   # 类似于构造方法
          self.doA()
          self.doB()
      
      
      if __name__ == "__main__":
      
          # lockA = threading.Lock()     # 普通锁
          # lockB = threading.Lock()
          lock = threading.RLock()       # Rlock 叫递归锁,可重用
          threads = []
          for i in range(5):
              threads.append(myThread())
          for t in threads:
              t.start()
          for t in threads:
              t.join()  # 等待线程结束,后面再讲。
      
      
    • 同步锁

          # 加锁后会加锁的部分变成串行
      
      import time
      import threading
      
      def addNum():
          global num  # 在每个线程中都获取这个变量
          print('fuck off')
          # num -= 1          #  此操作的时间远小于CPU切换的时间
      
          # 加锁,被加锁的部分是串行
      
          r.acquire()         #######  加锁
          temp = num          # 1
          # time.sleep(0.001)   # 2 有可能取了数99后,执行完这两步后CPU转到另外的线程上去了,
          print('ok')                    # 另外的线程取到99,执行减1,CPU再转回当前线程,又执行99-1,重复了
          time.sleep(0.0002)
          num = temp - 1
          r.release()         ######## 释放锁
      
      
      
      num = 100
      thread_list = []
      
      r = threading.Lock()    # python的GIL锁
      
      # 用for循环创建100个线程
      for i in range(100):
          t = threading.Thread(target=addNum)
          t.start()
          # t.join()     # join阻塞,可以得到正确的结果,从但是变成了串行,失去了多线程的意义
                         # join虽然可以得到正确结果,但是除了计算的其他部分也会变成并行
          thread_list.append(t)
      
      
      for t in thread_list:
          t.join()
      
      
      print("\nfinal num:", num)
      
      
      # num减1的速度如果
      
      # GIL保证只有一个线程进入解释器
      # 自己加的锁是锁CPU,在我释放锁之前你不要切换了
      
      
    • event

      # event 类似condition
      
      # event.isSet():返回event的状态值;
      #
      # event.wait():如果 event.isSet()==False将阻塞线程;
      #
      # event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
      #
      # event.clear():恢复event的状态值为False。
      
      
      import threading, time
      
      class Boss(threading.Thread):
          def run(self):
              print("BOSS: 今晚大家都要加班到22:00")
              event.is_set() or event.set()
              time.sleep(2)
              print("BOSS:<22:00>可以下班了。 ")
              event.is_set() or event.set()
      
      class Worker(threading.Thread):
          def run(self):
              event.wait()
              print("Worker:哎,命苦啊")
              time.sleep(0.25)
              event.clear()
              event.wait()
              print("Worker: OhYear!")
      
      
      
      
      
      if __name__ == "__main__":
          event = threading.Event()
          threads = []
          for i in range(5):
              threads.append(Worker())
          threads.append(Boss())
          for t in threads:
              t.start()
          for t in threads:
              t.join()
      
      
    • 多线程利器 QUEUE队列

          # 队列里本身就有一把锁
      #
      # import queue, time, threading
      #
      # d = queue.Queue(3)   #
      
      #  d.put('jinxing',0)  #插入数据
      # d.put('xiaohu')
      # d.put('haoran')
      #
      # print(d.get())
      # print(d.get())
      # print(d.get())
      #
      #
      # print(d.qsize())
      
      # li = [1,2,3,4,5]
      #
      # def pri():
      #     while li:
      #         a = li[-1]
      #         print(a)
      #         time.sleep(1)
      #         try:
      #             li.remove(a)
      #         except:
      #             print('----',a)
      #
      # t1 = threading.Thread(target=pri, args=())
      # t1.start()
      # t2 = threading.Thread(target=pri, args=())
      # t2.start()
      
      import threading, queue
      from time import sleep
      from random import randint
      
      
      class Production(threading.Thread):   #  生产者
          def run(self):
              while True:
                  r = randint(0, 100)
                  q.put(r)
                  print("生产出来%s号包子" % r)
                  sleep(1)
      
      
      class Proces(threading.Thread):       #  消费者
          def run(self):
              while True:
                  re = q.get()
                  print("吃掉%s号包子" % re)
                  sleep(1)
      
      
      if __name__ == "__main__":
          q = queue.Queue(10)
          threads = [Production(), Production(), Production(), Proces()]
          for t in threads:
              t.start()
      
      

    相关文章

      网友评论

        本文标题:多线程 -- threading

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