• 队列介绍,IPC机制


    队列

      队列的数据元素又称为队列元素。在队列中插入一个队列元素为入队,从队列中删除一个队列

    元素称为出队,因为队列只允许从一端插入,在另一端删除,所以只有最早进入队列的元素才能最

    先从队列中删除,因此队列又称为先进先出。

      队列的进程原理就是在内存中开辟出新的连续的独立内存空间,要想让这些独立的内存空间实

    现通信就得把它们用根线连接起来,就相当于两个独立的内存空间之间接入了一个管道实现互通,

    管道呢也就是队列加锁。

    代码实现:

    from multiprocessing import Queue
    
    q = Queue(5)  # 括号内可以传参数 表示的是这个队列的最大存储数
    # 往队列中添加数据
    q.put(1)
    q.put(2)
    print(q.full())  # 判断队列是否满了
    q.put(3)
    q.put(4)
    q.put(5)
    print(q.full())
    q.put(6)  # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.empty())  # 判断队列中的数据是否取完
    print(q.get())
    print(q.get())
    print(q.empty())
    print(q.get_nowait())  # 取值 没有值的时候不等待直接报错
    print(q.get())  # 当队列中的数据被取完之后 再次获取 程序会阻塞 原地等待 直到有人往队列中放入值

    进程间通信的IPC机制

      实现原理呢是先在__main__中创建队列,然后创建子进程,子进程中呢存入数据,再创建主进

    程获取子进程中存入的数据。

    from multiprocessing import Process,Queue
    
    def producer(q):
        q.put('hello ~')
    
    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()

    生产者消费者模型

      生产者呢就是生产或者制造数据的,消费者就是消费或者处理数据的。

    举个例子:比如包子铺的厨师他每天要做包子拿来卖,而我们呢每天吃早饭会去买包子,这时候做

    包子的厨师就是就是生产者,而买包子的我们呢就是消费者。

    代码实现:__main__内创建生产者做包子,消费者吃包子。

    from multiprocessing import Process,Queue,JoinableQueue
    import random
    import time
    
    
    def producer(name,food,q):
        for i in range(10):
            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()
            if data == None:break
            print('%s吃了%s'%(name,data))
            time.sleep(random.random())
            q.task_done()  # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了
    
    
    
    if __name__ == '__main__':
        q = JoinableQueue()
    
        p = Process(target=producer,args=('大厨1','馒头',q))
        p1 = Process(target=producer,args=('厨师跟班','生蚝',q))
        c = Process(target=consumer,args=('吃货1',q))
        c1 = Process(target=consumer,args=('吃货2',q))
        p.start()
        p1.start()
        c.daemon = True
        c1.daemon = True
        c.start()
        c1.start()
        p.join()
        p1.join()
    
        q.join()  # 等到队列中数据全部取出

    线程

      进程和线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物,但是呢线程它被包含在

    进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一的控制流,一个进程可以并

    发多个线程,每个线程呢能并行执行不同的任务,并且线程与线程之间数据是共享的,开启线程的

    开销要远远小于开启进程的开销。

    进程:资源单位
    线程:执行单位
      将内存比如成工厂,那么进程就相当于是工厂里面的车间而你的线程就相当于是车间里面的流水线
      每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中。

    开启线程的两种方式:

      开启线程不用在__main__内写,因为线程它不需要拷贝代码,也不需要从上往下的再执行一

    遍,但是我们会习惯的写入__main__内。

    #  第一种,不在__main__内写
    
    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('')
    
    
    #  第二种 
    
    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('')

    线程对象和其它方法:

    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)
    t = Thread(target=task,args=('egon',1))
    t1 = Thread(target=task,args=('jason',2))
    t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    t1.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    t1.join()  # 主线程等待子线程运行完毕
    print('当前正在活跃的线程数',active_count())
    # 小的代码执行完 线程就已经开启了
    print('')
    # print('主current_thread:',current_thread().name)
    # print('主',os.getpid())

    守护线程:

      一般情况下主线程的结束也就意味着进程的结束,但是在守护线程内主线程它必须要等待其它

    非守护线程的结束才能结束。通俗的来讲呢就是因为子线程在运行的时候需要使用进程的资源,但

    是主线程一旦结束资源也就销毁了。所以主线程必须等待其他非守护线程的结束才能结束

    from threading import Thread,current_thread
    import time
    
    def task(i):
        print(current_thread().name)
        time.sleep(i)
        print('GG')
    # for i in range(3):
    #     t = Thread(target=task,args=(i,))
    #     t.start()
    t = Thread(target=task,args=(1,))
    t.daemon = True
    t.start()
    print('')

    线程间通信:

    from threading import Thread
    
    money = 666
    
    def task():
        global money
        money = 999
    
    t = Thread(target=task)
    t.start()
    t.join()
    print(money)

    线程互斥锁:

    from threading import Thread,Lock
    import time
    
    n = 100
    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(100):
        t = Thread(target=task,args=(mutex,))
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(n)

      

  • 相关阅读:
    在CentOS 6.7 64位安装PHP的PDO_OCI扩展 Installing PDO_OCI extension on CentOS 6.7 64bit
    Windows下Apache+PHP+MySQL开发环境的搭建(WAMP)
    在Window上用cmd创建.htaccess文件
    Magento 0元订单 支付方式 -- Magento 0 Subtotal Payment Method
    PHP使用OPENSSL RSA加密解密数据
    CentOS编译安装PHP 7.0
    [转] CentOS单独安装Apache Benchmark压力测试工具的办法
    [转] 基于MySQL的秒杀核心设计(减库存部分)-防超卖与高并发
    快速激活JetBrains PhpStorm WebStorm系列产品
    Mac OS的phpize空信息解决办法
  • 原文地址:https://www.cnblogs.com/sweet-i/p/11341996.html
Copyright © 2020-2023  润新知