进程之间通信、线程

  • 去幕布 >>
  • 进程之间通信IPC机制
    • 队列:先进先出(队列=管道+锁)
      full、get_nowait、empty 都不适用于多进程的情况
    • 队列 的方法演示
      from multiprocessing import Queue
      ​
      q = Queue(3)  # 括号内可以传参数 表示的是这个队列的最大存储数
      # 往队列中添加数据
      q.put(1)
      q.put(2)
      print(q.full())  # 判断队列是否满了
      q.put(3)
      print(q.full())
      # q.put(4)  # 当队列满了之后,再放入数据 不会报错,会原地等待 直到队列中有数据被取走(阻塞态)
      print(q.get())
      print(q.get())
      print(q.empty())  # 判断队列中的数据是否取完
      print(q.get())
      print(q.empty())
      # print(q.get_nowait())  # 取值 没有值不等待直接报错(queue.Empty)
      print(q.get())  # 当队列中的数据被取完之后,再次获取,程序会阻塞 直到有人往队列中放入值
      
      
      ​​​
      '''执行结果
      False
      True
      1
      2
      False
      3
      True
      ​​'''​​​
      View Code
    • 进程间通信(IPC,InterProcess Communication)
      子进程放数据,主进程获取数据
      两个子进程相互 放 取数据
    • IPC 之队列方式 的代码演示
      from multiprocessing import Process,Queue
      ​
      def producer(q):
          q.put('hello GF~')
      def consumer(q):
          print(q.get())
      ​
      if __name__ == '__main__':
          q = Queue()
          p = Process(target=producer,args=(q,))
          c = Process(target=consumer, args=(q,))
          p.start()
          c.start()
      
      ​​
      '''执行结果:
      hello GF~
      '''​​​
      View Code
    • 生产者消费者模型
      生产者:生产/制造数据的
      消费者:消费/处理数据的
      例子:做包子的,买包子的
              1.做包子远比买包子的多
              2.做包子的远比包子的少
              供需不平衡的问题
      
      进程中的应用:
      将两个函数实例化为进程,通过队列通信,
      ​通过Joinable​​​Queue模块确定队列中的值是否取完
      理解
    • 生产者消费者模型 在进程中的应用
      from multiprocessing import Process,Queue,JoinableQueue
      import random
      import time
      ​
      def producer(name,food,q):
          for i in range(1):
              data = '%s生产的%s%s'%(name,food,i)
              time.sleep(random.random())
              q.put(data)
              print(data)
      ​
      def consumer(name,q):
          while True:
              data = q.get()
              print('%s吃了%s'%(name,data))
              time.sleep(random.random())
              q.task_done()  # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了
      if __name__ == '__main__':
          q = JoinableQueue()
          p = Process(target=producer,args=('大厨egon','馒头',q))
          p1 = Process(target=producer,args=('跟班tank','生蚝',q))
          c = Process(target=consumer,args=('许兆龙',q))
          c1 = Process(target=consumer,args=('吃货jerry',q))
          p.start()
          p1.start()
          c.daemon = True
          c1.daemon = True
          c.start()
          c1.start()
          p.join()
          p1.join()
      ​
          q.join()  # 等到队列中数据全部取出
      
      ​​
      '''执行结果:
      跟班tank生产的生蚝0
      吃货jerry吃了跟班tank生产的生蚝0
      大厨egon生产的馒头0
      许兆龙吃了大厨egon生产的馒头0
      Process finished with exit code 0
      ​​'''
      View Code
  • 线程
    什么是线程
        进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物
    ​
        进程:资源单位
        线程:执行单位
            将内存比如成工厂
            那么进程就相当于是工厂里面的车间
            而你的线程就相当于是车间里面的流水线
        ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中
        提供代码运行所需要的资源
    ​
    为什么要有线程
        开进程
            1.申请内存空间  耗资源
            2."拷贝代码"    耗资源
        开线程
            一个进程内可以起多个线程,并且线程与线程之间数据是共享的
        ps:开启线程的开销要远远小于开启进程的开销
    理解
    • 创建线程的两种方式
      # 第一种方式(直接调用Threading模块的Thread)from threading import Thread
      import time
      ​
      def task(name):
          print('%s is running'%name)
          time.sleep(3)
          print('%s is over'%name)
      ​
      # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
      t = Thread(target=task,args=('egon',))​
      t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
      # 等到代码执行完,实际上线程就已经开启了
      print('')
      ​​
      '''执行结果:
      ​​egon is running
      主
      egon is over
      '''​
      ​​​
      
      
      # 第二种方式(自定义Tread方法)from threading import Thread
      import time
      class MyThread(Thread):
          def __init__(self,name):
              super().__init__()
              self.name = name
          def run(self):
              print('%s is running'%self.name)
              time.sleep(3)
              print('%s is over'%self.name)
      t = MyThread('egon')
      t.start()
      print('')
      ​​​​
      '''执行结果:
      ​​egon is running
      主
      egon is over
      '''​​
      View Code
    • 线程对象及其他方法
      from threading import Thread,current_thread,active_count
      import time
      import os
      ​
      def task(name,i):
          print('%s is running'%name)
          # print('子current_thread:',current_thread().name)
          # print('子',os.getpid())
          time.sleep(i)
          print('%s is over'%name)
      # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
      t = Thread(target=task,args=('egon',1))
      t1 = Thread(target=task,args=('jason',2))
      t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
      t1.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
      t1.join()  # 主线程等待子线程运行完毕
      print('当前正在活跃的线程数',active_count())
      # 等到代码执行完 线程就已经开启了
      print('')
      ​
      ​'''执行结果:
      ​egon is running
      jason is running
      egon is over
      jason is over
      当前正在活跃的线程数 1
      主
      Process finished with exit code 0
      '''
      View Code
    • 守护线程
      主线程的结束也就意味着进程的结束
      主线程必须等待其他非守护线程的结束才能结束
      (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
      理解
    • 守护线程代码示例
      from threading import Thread,current_thread
      import time
      ​
      def task(i):
          print(current_thread().name)
          time.sleep(i)
          print('GG')
      ​
      t = Thread(target=task,args=(1,))
      t.daemon = True
      t.start()
      print('')
      ​
      '''执行结果:
      Thread-1
      主
      ​'''​​
      View Code
    • 线程之间通信
      from threading import Thread
      ​
      money = 666
      def task():
          global money
          money = 999
      ​
      t = Thread(target=task)
      t.start()
      t.join()
      print(money)
      ​
      '''执行结果:
      999
      '''
      View Code
    • 互斥锁在线程中的应用(将并行编程串行)
      from threading import Thread,Lock
      import time
      ​
      n = 10
      def task(mutex):
          global  n
          mutex.acquire()
          tmp = n
          time.sleep(0.1)
          n = tmp - 1
          mutex.release()
      ​
      t_list = []
      mutex = Lock()
      for i in range(10):
          t = Thread(target=task,args=(mutex,))
          t.start()
          t_list.append(t)
      for t in t_list:
          t.join()
      ​
      print(n)
      
      '''执行结果:
      0
      '''​​​​​
      View Code

 

posted @ 2019-08-12 17:00  不在一城  阅读(146)  评论(0编辑  收藏  举报