进程与线程

1 Python中的进程

在Python中,进程是指正在执行的程序实例

进程它是操作系统总最重要的概念,也是最基本的一个概念
线程也是操作系统中得一个很重要的概念

1.进程和线程都是有操作系统来调度使用的,我们程序员是不能控制的,这里就设计到调度算法

2.什么是进程? 线程? 什么是程序?

程序:一堆代码就是程序,它也没有生命周期
进程:它是有生命周期的,这个任务做完,进程就不存在了

3.例如
	"""
		厨师做饭,厨师做一道菜、应该有菜谱,安装菜谱的程序一步一步的做,在这个过程中,菜谱就是程序,程序就是路程. 做菜的过程就是进程,厨师就是线程,如果做菜完毕了,进程就不存在了,线程是进程中实际做事儿的.
	"""
    
4.在一个进程中,可以有多个线程,一个进程中只有一个线程,也是可以的。
5.一个进程中至少要有一个线程

6.进程和线程他们都是有操作系统来调度的,程序员级别是没办法来调度的,协程就是程序员级别的,协程的调度它就是有我们程序员自己来调度的,在操作系统中是没有协程这个概念的,是我么人为的抽象出来的


进程 >>> 线程  >>> 协程

他们三个消耗资源的对比:进程 >>> 线程 >>> 协程

进程调度算法(四种算法)

CPU的工作机制:

	1. 遇到I/O的时候,CPU会交出执行权限
    2. 当CPU遇到耗时比较长的时候,也会自动交出执行权限,切换到其他任务

I/O密集型
	"""他会被时间所阻塞,不会占用大量的CPU资源,比如sleep(3)"""
计算密集型
	"""不占用大量的时候,会占用大量的CPU资源,这种情况就是计算密集型,没有时间的大量消耗"""
    for i in range(10000000):
        i+=1
        
一、先来先服务调度算法
二、短作业优先调度算法
三、时间片轮转法
四、多级反馈队列

进程的并行和并发概念 

1.并行:统一时刻同时运行
	 如果CPU是单核的,同一时刻能不能做到同时执行多个任务,不能
     如果是多核的,统一时刻就能够做到了
     核是2,同一时刻最多执行2个任务
     核是4个,同一时刻最多执行4个任务
    
2.并发:一段时间内看起来是同时运行

	 如果是单核的CPU,你说,听歌、看视频、浏览网页能不能我一起操作? 能的,cpu的切换达到的
    
3.生活中有哪些是并发的例子:

	淘宝的双11的0点用户同时下单支付

2 Python中的线程

Python线程是一种轻量级的并发编程方式,可以同时执行多个任务。Python中线程是由线程对象(threading.Thread)来表示的,通过创建线程对象并调用其start()方法来启动线程。以下是一个简        烦烦烦烦烦烦烦                                 

在这个例子中,我们创建了两个线程对象t1和t2,并将它们分别指定了两个函数。然后我们通过调用start()方法启动线程并通过join()方法等待线程执行完成。注意,线程的执行是并发的,因此print_numbers()和print_letters()可能会交替执行。

3 同步异步,阻塞和非阻塞

同步:每一次的运行都要依赖于上一步的结果
异步:每次的运行结果不依赖于上次的结果

阻塞与非阻塞阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

阻塞调用 是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用 指在不能立刻得到结果之前,该调用不会阻塞当前线程。

例子:

你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

异步+非阻塞  :是效率最高的
同步+阻塞   :是效率最低的 

4 multiprocess模块

        仔细说来,multiprocess不是一个模块而是python中一个操作、管理进程的包。 之所以叫multi是取自multiple的多功能的意思,在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆,我将这部分大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。

4.1 multiprocess.process模块

process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。

4.2 process模块介绍

Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)

强调:

  1. 需要使用关键字的方式来指定参数
  2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

参数介绍:

  • group参数未使用,值始终为None
  • target表示调用对象,即子进程要执行的任务
  • args表示调用对象的位置参数元组,args=(1,2,'egon',)
  • kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
  • name为子进程的名称

3.1 方法介绍

p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程

3.2 属性介绍

p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置

p.name:进程的名称
p.pid:进程的pid
p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

3.3 Process类的几个方法

from multiprocessing import Process

import time
def task(name, age, gender):
    print(name, age, gender)
    # with open('a.txt', 'w', encoding='utf-8') as f:
    #     f.write('helloworld')
    time.sleep(3)
    print("子进程的代码")

"""现在这个写法还没有开启进程"""
"""Windows平台上必须写在这个里面"""
if __name__ == '__main__':
    """
    group=None, target=None, name=None, args=(), kwargs={},
                 *, daemon=None
    """
    # 子进程  主进程
    
    """只是通知操作系统去开进程,并不是立马把进程开起来,他是需要消耗一定的时间的,侧面的反应了开启进程其实消耗很大"""
    p = Process(target=task, name='process-2', args=(), kwargs={'name':'jerry', 'age':20, 'gender':'male'})  # 实例出来一个进程类, 让这个进程执行task任务
    p.start()  # 真正的开启进程
    # 操作系统是负责把这个进程开起来
    
    # 开启一个进程来执行task任务,真正是谁在执行这个任务,是线程,进程里面至少要有一个线程
    """进程的几个属性:1. 进程名 2. 进程号pid kill """
    # 如何查看进程的名称
     print(p.name) # Process-1
    # 怎么改进程名字
     p.name = '这是新的进程名'
    print(p.name)  # 这是新的进程名

    ## 如何查看进程号
    print(p.pid) # process id

    print(p.is_alive()) # True
    p.terminate() # 杀死进程,结束任务
    import time
    time.sleep(1)
    print(p.is_alive())
    p.join() # 等待子进程的代码全部执行完毕,在走主进程的
    print("主进程的代码执行完毕")

5 如何创建进程

from multiprocessing import Process


def task():
    with open('a.txt', 'w', encoding='utf-8') as f:
        f.write('helloworld')


"""Windows平台上必须写在这个里面"""

if __name__ == '__main__':

    p = Process(target=task)  # 实例出来一个进程类, 让这个进程执行task任务

    p.start()  # 真正的开启进程

6 如何创建线程

多进程就意味着可以同时做多个任务嘛, 一个进程做一个任务,多个进程肯定是做多个任务
from multiprocessing import Process

import time
def task(name):
    # print(name)
    # with open('a.txt', 'a', encoding='utf-8') as f:
    #     f.write('helloworld')
    print("子进程")
    time.sleep(1)
if __name__ == '__main__':
    """理论上你是可以一直开进程,单是你需要考虑资源的消耗情况"""
    start_time = time.time()
    ll = []
    for i in range(10):
        p=Process(target=task, kwargs={'name':'kevin'})
        p.start()
        # p.join() #
        ll.append(p)

    for j in ll:
        j.join()

    print("主进程, 总时间:", time.time() - start_time)

7 基于TCP协议的高并发程序

一个服务端不能够同时给多个客户端发送消息
import socket  # python提供的socket模块

def task(conn):
    while True:
        try:
            # 异常了一个bug,粘包现象
            data = conn.recv(1024)  # 括号里面写的是接收的字节数,最多接收1024个字节
            if len(data) == 0:
                continue
            print(data)  # 还是bytes类型

            # 服务端开始给客户端也发送一个数据
            conn.send(data.upper())
        except Exception as e:
            print(e)
            break

    conn.close()


from multiprocessing import Process

if __name__ == '__main__':
    # 1. 买手机
    # SOCK_STREAM  ====> 代表的是TCP协议
    # socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp协议
    server = socket.socket()  # 默认是TCP协议

    # 2. 买手机卡
    # '0.0.0.0'  =====> 代表允许任何的ip链接
    # server.bind(('0.0.0.0', 8000)) # 服务端绑定一个地址
    server.bind(('127.0.0.1', 8001))  # 服务端绑定一个地址

    # 3. 开机
    server.listen(1)  # 监听,半连接池
    print('服务端正在准备接收客户端消息:')
    while True:
        conn, client_addr = server.accept()  # 接收,  程序启动之后,会在accept这里夯住,阻塞
        p = Process(target=task, args=(conn,))
        p.start()

 

你可能感兴趣的:(前端,服务器)