zoukankan      html  css  js  c++  java
  • Day35

    #进程间通讯
    # multiprocessing.Queue()
    # 进程间通讯采用的是队列的模式,Queue中存放各个进程处理好的数据,再交由其他进程提取数据
    # 是典型的生产者消费者模型
    # 在父进程中创建两个子进程,两个子进程间的通讯是通过Queue队列,一个子进程拿数据,另一个子进程输入数据
    #————————————————————————————————————————————————————#
    #multiprcessing.Queue.put() 为 入队操作
    #multiprcessing.Queue.get() 为 出队操作
    # put(obj[, block[, timeout]])
    # 将obj放入队列。 如果可选参数 block为True(默认值),timeout为None(默认值),则必要时阻止,
    # 直到空闲插槽可用。 如果超时是正数,它将阻止最多超时秒数,如果在该时间内没有空闲插槽可用,
    # 则会引发Queue.Full异常。
    # 否则(块为False),如果空闲插槽立即可用,则将一个项目放在队列中,
    # 否则会引发Queue.Full异常(在这种情况下,忽略超时)。
    #————————————————————————————————————————————————————#
    # get([block[, timeout]])
    # 从队列中删除并返回一个项目。 如果可选的args块为True(默认值),超时为None(默认值),
    # 则在必要时阻止,直到项目可用。 如果超时为正数,则它将阻塞至多超时秒数,
    # 并在该时间内没有可用项目时引发Queue.Empty异常。
    # 否则(block为False),如果一个项目立即可用,返回一个项目,
    # 否则会引发Queue.Empty异常(在这种情况下,忽略超时)。
    #————————————————————————————————————————————————————#
    # multiprocessing.Pipe()
    # Pipe()函数返回一对由管道连接的连接对象,默认情况下是双工(双向)。
    # Pipe()返回的两个连接对象代表管道的两端。 每个连接对象都有send()和recv()方法(等等)。
    # 请注意,如果两个进程(或线程)尝试同时读取或写入管道的同一端,管道中的数据可能会损坏。
    # 当然,同时使用管道不同端的过程也会有风险。
    # 返回表示管道末端的一对Connection(conn1,conn2)对象。
    # 如果duplex为True(默认),则管道是双向的。
    # 如果duplex是False,那么管道是单向的:conn1只能用于接收消息,conn2只能用于发送消息。
    # from multiprocessing import Process,Pipe
    # def foo(conn):
    # conn.send([12,'good',{'name':'alex'}])
    # response = conn.recv()
    # print('response:',response)
    # conn.close()
    # print('ID2:',id(conn))
    # if __name__ == '__main__':
    # parent_conn,child_conn = Pipe()
    # print('ID1:',id(child_conn))
    # p = Process(target=foo,args=(child_conn,))
    # p.start()
    # print(parent_conn.recv())
    # parent_conn.send('Hello son')
    # p.join()
    #————————————————————————————————————————————————————#
    #———————————————————————进程同步—————————————————————————#
    # 线程同步是因为共享了数据,进程是完全独立的两份数据,没有同步,即不用加锁
    # 多个进程有可能共用多个资源,在进程中虽然内存是相互独立的,但是也会有公共资源
    # from multiprocessing import Process,Lock
    # import time
    # def f(l,i):
    # # with l.acquire():
    # print('hello world%s'%i)
    # if __name__ == '__main__':
    # lock = Lock()
    # for num in range(10):
    # time.sleep(1)
    # Process(target=f,args=(lock,num)).start()
    # ———————————————————————进程池—————————————————————————#
    # from multiprocessing import Process,Pool
    # import time,os
    # def Foo(i):
    # time.sleep(1)
    # print(i)
    # return i+100
    # def Bar(arg):
    # print('我是被调用的函数')
    # # print('logger:',arg)
    # if __name__ == '__main__':
    #
    # pool = Pool(5)
    # Bar(1)
    # # print("----------------")
    # for i in range(100):
    # # pool.apply(func=Foo, args=(i,))
    # # callback 回调函数:就是某个动作或者函数执行成功后再去执行的函数
    # pool.apply_async(func=Foo, args=(i,),callback=Bar)
    # # pool.apply_async(func=Foo, args=(i,))
    # pool.close()#进程池里close必须放在join前
    # pool.join()
    # print('end')
    # ——————————————————————————————————————————————————#
    # ——————————————————————协程——————————————————————————#
    # python的多线程的特点是不能用多核,只能使用一个核不断切换,不能真正的实现并行
    # 在python不断在优化协程,解决并发效率能提供很多方案
    # 协程,又称微线程,纤程。英文名Coroutine。协作式,非抢占式。
    # 协程也是不断的切换,由程序员不断的调度,根据上下文协议保护数据
    # 协程主要面向的也是IO操作
    # import time,requests
    # start = time.time()
    # def f(url):
    # print('Get:%s'%url)
    # resp = requests.get(url)
    # data = resp.text
    # print('%d bytes received from %s'%(len(data),url))
    # f('https://www.baidu.com/')
    # print('cost time:',time.time()-start)
    # import gevent
    # import requests,time
    # start=time.time()
    # def f(url):
    # print('GET: %s' % url)
    # resp =requests.get(url)
    # data = resp.text
    # print('%d bytes received from %s.' % (len(data), url))
    #
    # f('https://www.python.org/')
    # f('https://www.yahoo.com/')
    # f('https://www.baidu.com/')
    # f('https://www.sina.com.cn/')
    # f("http://www.xiaohuar.com/hua/")
    #
    # # gevent.joinall([
    # # gevent.spawn(f, 'https://www.python.org/'),
    # # gevent.spawn(f, 'https://www.yahoo.com/'),
    # # gevent.spawn(f, 'https://www.baidu.com/'),
    # # gevent.spawn(f, 'https://www.sina.com.cn/'),
    # # gevent.spawn(f, 'http://www.xiaohuar.com/hua/'),
    # # ])
    #
    # # f('https://www.python.org/')
    # #
    # # f('https://www.yahoo.com/')
    # #
    # # f('https://baidu.com/')
    #
    # # f('https://www.sina.com.cn/')
    #
    # print("cost time:",time.time()-start)
    # ——————————————————————协程——————————————————————————#
    # python的多线程的特点是不能用多核,只能使用一个核不断切换,不能真正的实现并行
    # 在python不断在优化协程,解决并发效率能提供很多方案
    # 协程,又称微线程,纤程。英文名Coroutine。协作式,非抢占式。
    # 协程也是不断的切换,由程序员不断的调度,根据上下文协议保护数据
    # def f():
    # print('ok')
    # yield
    # f()
    # greenlet是一个用C实现的协程模块,相比与python自带的yield,
    # 它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
    # from greenlet import greenlet
    # def test1():
    # print(12)
    # gr2.switch()
    # print(34)
    # gr2.switch()
    # def test2():
    # print(56)
    # gr1.switch()
    # print(78)
    # gr1 = greenlet(test1)
    # gr2 = greenlet(test2)
    # gr1.switch()
    # ——————————————————————协程——————————————————————————#
    #—————————————————————简易爬虫——————————————————————————#
    # import gevent
    # import requests,time
    # start = time.time()
    # def f(url):
    # print('Get:%s'%url)
    # resp = requests.get(url)
    # data = resp.text
    # print('%d bytes received from: %s'%(len(data),url))
    # gevent.joinall([
    # gevent.spawn(f,'https://www.python.org/'),
    # gevent.spawn(f, 'https://www.yahoo.com/'),
    # gevent.spawn(f, 'https://www.baidu.com/'),
    # gevent.spawn(f, 'https://www.sina.com.cn/'),
    # ])
    # print('Cost time:',time.time()-start)
    #—————————————————————简易爬虫——————————————————————————#
    # 事件驱动模型(线性模式和触发机制的碰撞)
    # 传统的编程是如下线性模式的:
    # 开始--->代码块A--->代码块B--->代码块C--->代码块D--->......--->结束
    # 每一个代码块里是完成各种各样事情的代码,但编程者知道代码块A,B,C,D...的执行顺序,
    # 唯一能够改变这个流程的是数据。输入不同的数据,根据条件语句判断,
    # 流程或许就改为A--->C--->E...--->结束。
    # 每一次程序运行顺序或许都不同,但它的控制流程是由输入数据和你编写的程序决定的。
    # 如果你知道这个程序当前的运行状态(包括输入数据和程序本身),
    # 那你就知道接下来甚至一直到结束它的运行流程。
    # 对于事件驱动型程序模型,它的流程大致如下:
    # 开始--->初始化--->等待
    # 与上面传统编程模式不同,事件驱动程序在启动之后,
    # 就在那等待,等待什么呢?等待被事件触发。
    # 传统编程下也有“等待”的时候,比如在代码块D中,
    # 你定义了一个input(),需要用户输入数据。
    # 但这与下面的等待不同,传统编程的“等待”,
    # 比如input(),
    # 你作为程序编写者是知道或者强制用户输入某个东西的,
    # 或许是数字,或许是文件名称,
    # 如果用户输入错误,你还需要提醒他,
    # 并请他重新输入。
    # 事件驱动程序的等待则是完全不知道,
    # 也不强制用户输入或者干什么。
    # 只要某一事件发生,那程序就会做出相应的“反应”。
    # 这些事件包括:输入信息、鼠标、敲击键盘上某个键还有系统内部定时器触发。
    #————————————————————————————————————#
    # 同步、异步、阻塞和非阻塞是相互独立的
    # 用户空间与内核空间
    # 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。
    # 操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。
    # 为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操心系统将虚拟空间划分为两部分,
    # 一部分为内核空间,一部分为用户空间。
    # 针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,
    # 称为内核空间,而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为用户空间。
    # 进程切换
    # 为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,
    # 并恢复以前挂起的某个进程的执行。这种行为被称为进程切换,
    # 这种切换是由操作系统来完成的。因此可以说,任何进程都是在操作系统内核的支持下运行的,
    # 是与内核紧密相关的。
    # 从一个进程的运行转到另一个进程上运行,这个过程中经过下面这些变化:
    # 保存处理机上下文,包括程序计数器和其他寄存器。
    # 更新PCB信息。
    # 把进程的PCB移入相应的队列,如就绪、在某事件阻塞等队列。
    # 选择另一个进程执行,并更新其PCB。
    # 更新内存管理的数据结构。
    # 恢复处理机上下文。
    # 注:总而言之就是很耗资源的
    #
    # 进程的阻塞
    #
    # 正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、
    # 新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),
    # 使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,
    # 也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。当进程进入阻塞状态,
    # 是不占用CPU资源的。
    #
    # 文件描述符fd
    #
    # 文件描述符(File descriptor)是计算机科学中的一个术语,
    # 是一个用于表述指向文件的引用的抽象化概念。
    # 文件描述符在形式上是一个非负整数。
    # 实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。
    # 当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。
    # 在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。
    # 但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
    #
    # 缓存 I/O
    #
    # 缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。
    # 在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,
    # 也就是说,数据会先被拷贝到操作系统内核的缓冲区中,
    # 然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。
    # 用户空间没法直接访问内核空间的,内核态到用户态的数据拷贝
    #
    # 思考:为什么数据一定要先到内核区,直接到用户内存不是更直接吗?
    # 缓存 I/O 的缺点:
    # 数据在传输过程中需要在应用程序地址空间和内核进行多次数据拷贝操作,
    # 这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。
    #————————————————————————————————————#
    # IO阻塞
    # import socket
    # sk = socket.socket()
    # sk.bind(('10.30.40.61',8080))
    # sk.listen(5)
    # while 1:
    # conn,addr = sk.accept()
    # while 1:
    # conn.send('hello'.encode('utf-8'))
    # data = conn.recv(1024)
    # print(data.decode('utf-8'))
    #————————————————————————————————————#

    #—————————————————————Select模块———————————————————————————#
    import socket
    import select
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen(5)
    inp =[sk,]
    while True:
    r,w,e = select.select(inp,[],[],2)
    for i in r:
    conn,addr = i.accept()
    print(conn)
    print('hello')
    inp.append(conn)
    print('>>>>')
    #————————————————————————————————————————————————————#
    # 触发方式:
    # 1.水平触发
    # 2.边缘触发
    # select---IO多路复用的好处:可以同时监听多个链接
    Win a contest, win a challenge
  • 相关阅读:
    SM2加解密代码示例
    RSA加解密代码示例
    base64加解密示例
    Hutool-数据类型转换
    Hutool工具-定时任务的使用
    Java面试题(5)mybatis、数据库
    Java面试题(4)Spring
    List、List<object>、List<?>三者的区别
    关于鉴权,看懂这篇就够了
    raft之一致性算法raft
  • 原文地址:https://www.cnblogs.com/pandaboy1123/p/8585049.html
Copyright © 2011-2022 走看看