网络并发编程面试题51-60

什么是反向代理和反向代理?

# 答案:
'''
反向代理,这个词相信搞网络的朋友都很熟悉的,但是具体是什么意思呢?说实话,复杂的我也不懂,就我个人理解而言,反向代理有很多用途,比如说保护真实服务器不被外界攻击,加速网络等等。今天我们要介绍的就是加速网络的一种。
'''

创建进程:

'''
1.首先要导入multiprocessing中的Process;
2.创建一个Process对象;
3.创建Process对象时,可以传递参数;

1.p = Process(target=XXX, args=(元组,) , kwargs={key:value}) 
2.target = XXX 指定的任务函数,不用加() 
3.args=(元组,) , kwargs={key:value} 给任务函数传递的参数 
4.使用start()启动进程;
5.结束进程。
'''

给子进程指定函数传递参数Demo:

import os
from multiprocessing import Process
import time
def pro_func(name, age, **kwargs):
    for i in range(5):
    print("子进程正在运行中,name=%s, age=%d, pid=%d" %(name, age, os.getpid()))
    print(kwargs)
    time.sleep(0.2)
if __name__ == '__main__':
    # 创建Process对象
    p = Process(target=pro_func, args=('小明',18), kwargs={'m': 20})
    # 启动进程
    p.start()

time.sleep(1) # 1秒钟之后,立刻结束子进程 17.
p.terminate()
p.join() 注意:进程间不共享全局变量。

进程之间的通信-Queue

在初始化Queue()对象时,(例如q=Queue(),若在括号中没有指定最大可接受的消息数量,或数
量为负值时,那么就代表可接受的消息数量没有上限-直到内存的尽头)

进程间通信Demo:

from multiprocessing import Process, Queueimport os, time, random # 写数据进程执行的代码:def write(q):
for value in ['A', 'B', 'C']:
    print('Put %s to queue...' % value)
    q.put(value)
    time.sleep(random.random())

读数据进程执行的代码:def read(q):

while True:
if not q.empty():
    value = q.get(True)
    print('Get %s from queue.' % value)
    time.sleep(random.random())
else:
    break
if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()

    # 等待pw结束:
    pw.join()

    # 启动子进程pr,读取:
    pr.start()
    pr.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    print('')
    print('所有数据都写入并且读完') 进程池Pool
from multiprocessing import Poolimport os, time, random
def worker(msg):
    t_start = time.time()
    print("%s开始执行,进程号为%d" % (msg,os.getpid()))
    # random.random()随机生成0~1之间的浮点数 7.    time.sleep(random.random()*2)
    t_stop = time.time()
    print(msg,"执行完毕,耗时%0.2f" % (t_stop-t_start))
    po = Pool(3)  # 定义一个进程池,最大进程数3
    for i in range(0,10): 13.    # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
    # 每次循环将会用空闲出来的子进程去调用目标    po.apply_async(worker,(i,))
    print("----start----")
    po.close()  # 关闭进程池,关闭后po不再接收新的请求 po.join()  # 等待po中所有子进程执行完成,必须放在close 语句之后 print("-----end-----")

multiprocessing.Pool 常用函数解析:

apply_async(func[, args[, kwds]]):使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
进程池中使用Queue
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的 Queue(),而不是
multiprocessing.Queue(),否则会得到一条如下的错误信息:

RuntimeError: Queue objects should only be shared between processes through
inheritance.
from multiprocessing import Manager,Poolimport os,time,random
def reader(q):
    print("reader启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    for i in range(q.qsize()):
    print("reader从Queue获取到消息:%s" % q.get(True))
def writer(q):
    print("writer启动(%s),父进程为(%s)" % (os.getpid(), os.getppid()))
    for i in "itcast":
    q.put(i)
if __name__=="__main__":
    print("(%s) start" % os.getpid())
    q = Manager().Queue()  # 使用Manager中的Queue
    po = Pool()
    po.apply_async(writer, (q,))
    time.sleep(1)

    # 先让上面的任务向Queue存入数据,然后再让下面的任务开始从中取数据 po.apply_async(reader, (q,))
    po.close()
    po.join()
    print("(%s) End" % os.getpid())

谈谈你对多进程,多线程,以及协程的理解,项目是否用?

这个问题被问的概率相当之大,其实多线程,多进程,在实际开发中用到的很少,除非是那些对项目性能要求特别高的,有的开发工作几年了,也确实没用过,你可以这么回答,给他扯扯什么是进程,线程(cpython中是伪多线程)的概念就行,实在不行你就说你之前写过下载文件时,用过多线程技术,或者业余时间用过多线程写爬虫,提升效率。

'''
进程:一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最
小单位,进程拥有自己独立的内存空间,所以进程间数据不共享,开销大。

线程:  调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程存在一个进程至少有一个线程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率。

协程:是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。

协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存
器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切
换非常快。
'''

解释一下什么是锁,有哪几种锁?

# 锁(Lock)是 Python 提供的对线程控制的对象。有互斥锁、递归锁。

什么是死锁呢?

'''
若干子线程在系统资源竞争时,都在等待对方对某部分资源解除占用状态,结果是谁也不愿先解锁,互相干等着,程序无法执行下去,这就是死锁。
GIL锁(有时候,面试官不问,你自己要主动说,增加b格,尽量别一问一答的尬聊,不然最后等到的一句话就是:你还有什么想问的么?)
GIL锁 全局解释器锁(只在cpython里才有)
作用:限制多线程同时执行,保证同一时间只有一个线程执行,所以cpython里的多线程其实是伪多线程!
所以Python里常常使用协程技术来代替多线程,协程是一种更轻量级的线程,
进程和线程的切换时由系统决定,而协程由我们程序员自己决定,而模块gevent下切换是遇到了耗时操作才会切换。
三者的关系:进程里有线程,线程里有协程。
'''
posted @ 2019-12-15 20:33  極9527  阅读(122)  评论(0编辑  收藏  举报